Tools For Visual Basic
Tools For Visual Basic
Release 6.0
RPMN-TVB0-0000600
6/2004
Copyright
Manual copyright 2004 Great Plains Software, Inc. All rights reserved. Great Plains
Software, Inc. is a wholly-owned subsidiary of Microsoft Corporation.
Your right to copy this documentation is limited by copyright law and the terms of the
software license agreement. As the software licensee, you may make a reasonable
number of copies or printouts for your own use. Making unauthorized copies,
adaptations, compilations, or derivative works for commercial distribution is
prohibited and constitutes a punishable violation of the law.
Trademarks
Great Plains, Dynamics, eEnterprise, Dexterity, Solomon IV, and Solomon Software
are either registered trademarks or trademarks of Great Plains Software, Inc. in the
United States and/or other countries. Great Plains Software, Inc. is a wholly-owned
subsidiary of Microsoft Corporation. Microsoft, ActiveX, BackOffice, BizTalk,
FrontPage, JScript, Outlook, SourceSafe, Verdana, Visual Basic, Visual C++, Visual
C#, Visual InterDev, Visual SourceSafe, Visual Studio, Win32, Windows, and
Windows NT are either registered trademarks or trademarks of Microsoft Corporation
in the United States and/or other countries.
The names of actual companies and products mentioned herein may be trademarks or
registered marks - in the United States and/or other countries - of their respective
owners.
The example companies, organizations, products, domain names, e-mail addresses,
logos, people, places, and events depicted herein are fictitious. No association with any
real company, organization, product, domain name, e-mail address, logo, person,
place, or event is intended or should be inferred.
Warranty disclaimer
Great Plains Software, Inc. and Microsoft Corporation disclaim any warranty
regarding the sample code contained in this documentation, including the warranties of
merchantability and fitness for a particular purpose.
Limitation of liability
The content of this manual is furnished for informational use only, is subject to change
without notice, and should not be construed as a commitment by Great Plains
Software, Inc. or Microsoft Corporation. Great Plains Software, Inc. and Microsoft
Corporation assume no responsibility or liability for any errors or inaccuracies that
may appear in this manual. Neither Great Plains Software, Inc., Microsoft Corporation
nor anyone else who has been involved in the creation, production or delivery of this
documentation shall be liable for any indirect, incidental, special, exemplary or
consequential damages, including but not limited to any loss of anticipated profit or
benefits, resulting from the use of this documentation or sample code.
License agreement
Use of this product is covered by a license agreement provided with the software
product. If you have any questions, please call the Microsoft Business Solutions
Customer Assistance Department at 800-456-0025 or 701-281-6500.
Publication date
June 2004
Part number
RPMN-TVB0-0000600
Introduction
iii
Table of Contents
Introduction
15
iv
41
Reference
71
Controls ..................................................................................................................................................71
SAFDate Control .....................................................................................................................71
SAFFloat Control.....................................................................................................................73
SAFInteger Control..................................................................................................................75
SAFMaskedText Control .........................................................................................................77
SAFGrid Control......................................................................................................................79
SAFCheck Control...................................................................................................................82
SAFCombo Control .................................................................................................................84
SAFOption Control ..................................................................................................................85
SAFUpdate Control..................................................................................................................87
Properties................................................................................................................................................88
Alignment Property..................................................................................................................88
BackColor Property..................................................................................................................89
BlankErr Property ....................................................................................................................90
Caption Property ......................................................................................................................91
ColsFrozen Property ................................................................................................................92
Custom Property Page..............................................................................................................93
Introduction
Customizable Property.............................................................................................................94
DBNav Property ......................................................................................................................95
DecimalPlaces Property ...........................................................................................................98
Default Property.......................................................................................................................99
DragIcon Property..................................................................................................................100
DragMode Property ...............................................................................................................100
Enabled Property....................................................................................................................101
FalseText Property.................................................................................................................101
FieldClass Property................................................................................................................102
Flex Key Fieldclasses ............................................................................................................103
Non-Flex Key Fieldclasses ....................................................................................................106
FieldName Property...............................................................................................................112
Font Property .........................................................................................................................113
ForeColor Property ................................................................................................................113
Heading Property ...................................................................................................................114
Height Property......................................................................................................................115
HelpContextID Property ........................................................................................................116
Index Property........................................................................................................................117
InGrid Property ......................................................................................................................118
Left Property ..........................................................................................................................119
Level Property........................................................................................................................120
Levels Property ......................................................................................................................121
List Property ..........................................................................................................................123
Mask Property........................................................................................................................124
Max Property .........................................................................................................................125
Min Property ..........................................................................................................................126
MouseIcon Property...............................................................................................................126
MousePointer Property ..........................................................................................................127
Name Property .......................................................................................................................127
NoteButton Property ..............................................................................................................128
NoteColumn Property ............................................................................................................129
PV Property ...........................................................................................................................130
Separator Property .................................................................................................................133
Spin Property .........................................................................................................................133
SpinIncrement Property .........................................................................................................134
TabIndex Property .................................................................................................................134
TabStop Property ...................................................................................................................135
Tag Property ..........................................................................................................................135
ToolTipText Property ............................................................................................................136
Top Property ..........................................................................................................................137
Trigger Property.....................................................................................................................138
TrueText Property..................................................................................................................141
Visible Property .....................................................................................................................142
WhatsThisHelpID Property ...................................................................................................143
Width Property.......................................................................................................................144
vi
Introduction
vii
CuryInfoSet Statement...........................................................................................................215
CuryRateTypeSet Statement ..................................................................................................218
CurySelFieldEnable Statement ..............................................................................................220
DateCheck Function ..............................................................................................................224
DateCmp Function.................................................................................................................224
DateMinusDate Function .......................................................................................................225
DatePlusDays Statement........................................................................................................226
DatePlusMonthSetDay Statement..........................................................................................227
DateToIntlStr Function ..........................................................................................................228
DateToStr Function................................................................................................................229
DateToStrSep Function..........................................................................................................229
DBNavFetch Functions..........................................................................................................230
DecimalPlaces Statement.......................................................................................................232
DetailLoad Statement.............................................................................................................235
DetailSave Statement .............................................................................................................237
DetailSetup Functions............................................................................................................238
DetailSetupExtend Function ..................................................................................................241
DispField Statements .............................................................................................................243
DispForm Statement ..............................................................................................................245
DisplayMode Statement.........................................................................................................246
DisplayModeSetProps Statement...........................................................................................247
DParm Function.....................................................................................................................248
ExportCustom Function .........................................................................................................249
FPAdd Function.....................................................................................................................252
FParm Function......................................................................................................................253
FPDiv Function......................................................................................................................254
FPMult Function ....................................................................................................................255
FPRnd Function .....................................................................................................................256
FPSub Function......................................................................................................................258
FtoA Function ........................................................................................................................259
GetCuryRate Statement .........................................................................................................260
GetModulePeriod Function....................................................................................................262
GetPrecCury Function ...........................................................................................................263
GetPrecision Function............................................................................................................265
GetSqlType Function .............................................................................................................266
GetSWIMDefaultPrintInfo Function .....................................................................................267
GetSWIMPrintInfo Function .................................................................................................269
GetSysDate Statement ...........................................................................................................270
GetSysTime Statement...........................................................................................................270
Grid_Sortable Statement........................................................................................................271
HideForm Statement ..............................................................................................................272
HideNoteButtons Statement...................................................................................................272
ImportCustom Function .........................................................................................................273
IncrStrg Statement .................................................................................................................277
InitLocalizationSubsystem Function......................................................................................278
IntlStrToDate Statement ........................................................................................................280
IParm Function ......................................................................................................................281
viii
Introduction
ix
427
Introduction
Introduction
About This Manual
To help you quickly become productive with Tools for Visual Basic, Microsoft
Business Solutions requires completion of the hands-on Tools for Visual Basic training
course. This course helps you achieve maximum return on your investment in Tools for
Visual Basic, and this manual is organized based on the assumption that you have
already attended this course. It is advisable that you periodically refer to the Tools for
Visual Basic Solomon Training manual for hands-on reinforcement on the topics in
this manual.
Module Overview
The Microsoft Business SolutionsSolomon Tools for Visual Basic is the same
development platform used by Microsoft Business Solutions to create Solomon. These
tools allow you to leverage your existing knowledge of Microsoft SQL Server and
Visual Basic to create a tightly integrated, complete line of business applications.
Speed of development
Finally, after youve mastered Tools for Visual Basic, you will find that much of
the standard, routine programming work required for all database applications is
handled automatically for you. This will make your development time significantly
shorter then with traditional PC-based development tools.
Note that the referential integrity, data flow, and business rules are not incorporated in
either the Solomon kernel or the database itself. Maintaining the logical integrity of the
data in the Solomon database is the responsibility of you, the programmer, although
features of the Tools make this easier.
There are many standard files that must be included in any Tools for Visual Basic
project. Most of these files should never be modified.
Almost every data entry, maintenance, or process window you might need will
probably be a completely separate executable.
You may be moving your development environment from one computer to another
(for example, from a desktop to a laptop).
Given these conditions, the directory structure shown in the following figure may be
useful to you. Notice that the directory is created with the same name as the application
that is being developed and is contained within the same subdirectory as the Solomon
subdirectory.
By using this structure, the VB project file can include the necessary common files
from Solomon and Tools for Visual Basic development folders using relative paths. All
files unique to the project can be centralized within the ST26000 directory.
Introduction
This structure facilitates moving the project to a different version of Solomon, or
moving the project to a different computer. It also facilitates the use of version control
software, which typically rely on a rigid directory structures for checking files in and
out.
Project Sub
directory is at the
same level as the
Sol4 subdirectory
VBProject.vbp &
Form1.frm are copied to
the project subdirectory
and renamed to match
the project name
Application server
Copy/paste
Customization manager
Detail grids
International localization
Mouse/keyboard conventions
Notes
Object Model
Security model
Status bar
Templates
Toolbar navigation
Transaction Import
The following sections describe the VB development environment, screen design, and
database considerations.
Introduction
Applic.dh
Swim.bas
VbtApp.cls
New_form.frm
Form1.frm
Swimapi.dll
Note: These files should be installed in the Solomon\VT\VB5_DEV folder. If they are
not there, add them using VB Code Inspector.
The following references are required in every VB Tools project file:
SAF.OCX
If this reference does not exist, VB Code Inspector cannot recognize the project as
a VB Tools application.
SAFDes.OCX
If this reference is missing, add it using VB Code Inspector.
SAFCont.OCX
If this reference is missing, add it using VB Code Inspector.
TabCtl32.OCX
If this reference is missing, add it using VB Code Inspector.
Screen Design
Controls
The following controls are required for a VB Tools project:
SAFContainer
SAFDesigner
SAFNewFrame
SAFNewTab
Form1
The Form1.Caption property must contain the .EXE name in parentheses in the form of
MyAppTitle (MM.SSS.SS) where the application name is MMSSSSS.EXE. Failure to
follow this standard results in a runtime error saying that the application does not
match the caption. This is checked by VB Code Inspector.
Events
The Form1 Form_Load events process in the following order.
LoadForm() calls
Applinit
SetAddr calls
SqlCursorEX calls
CurrencyInfo calls
ScreenInit
DetailSetup calls
Introduction
Property Considerations
SAFMaskedText a Mask property is required for this control type. This is checked
by VB Code Inspector. The Mask property should never be larger than the actual field
size. That would result in the value for the control not displaying at all. This is checked
by VB Code Inspector.
The Mask property should in most cases, match the length of the field defined for that
control. If one application populates the full length and another application shows only
a portion of that value, information is truncated, and if updated to other records the
truncated value is passed along. This is optionally checked by VB Code Inspector if the
Warning Option for Controls with a Mask that is smaller than the fields defined size
is selected.
Setting property values at runtime Avoid using control.property = somevalue.
Customization Manager has no knowledge of properties set using this method. The
correct method is to use the Setprops and/or MsetProp Solomon APIs. This is
optionally checked by VB Code Inspector if the Warning Option for Explicit Property
Assignments vs SetProps is selected.
Triggers The maximum number of controls with a trigger property that points to a
single control is 8.
PV or DBNav property If the stored procedure being used contains a LIKE
keyword, the wildcard checkbox should be checked. The property should be
populated for the last key field of every Navigation and Lookup level. This is
optionally checked by VB Code Inspector if the Warning Option No PV or DBNAV
property on last key field of Navigation level is selected.
The maximum number of parameters allowed for a PV or DBNav is 8. When passing
an integer parameter to DBNAV to retrieve multiple rows, use the BETWEEN
keyword in the WHERE clause of the Select statement.
Control Size The size of all controls that contain text information (that is,
SAFMaskedText, Labels, SAFCombo) should be 35% larger size than the English text
requires (for international language support).
Tab order
The tabindex of a label that corresponds to a control should immediately precede the
tabindex of that control. When using Hot Key mnemonics (i.e., &Detail) for control
positioning, the Solomon kernel positions the cursor at the control whose tabindex
value follows the tabindex value for the label where the hot key is identified. If this is
not done and a user customizes the label to add a Hot Key, the cursor is positioned on
the next SAFControl in tab ordernot necessarily the next control visually.
When in a grid screen, it is important to make the grid container (that is, Frame) the
first tabindex value, then all controls and labels within the frame should have
contiguous tabindex values. This is optionally checked by VB Code Inspector if the
Warning Option Tabindex values that jump out and back into a container is selected.
The tabindex should never be set to allow the cursor to move from inside the grid to
outside of the grid, then back into the grid. This is optionally checked by VB Code
Inspector if the Warning Option Tabindex values that jump out and back into a
container is selected.
Levels
The levels identified in the Level property of the Update control must match the levels
specified in the SQLCursorEX calls.
The data for this property is formatted so that the level identified as LEVEL0 should be
first. LEVEL1 second, and so forth. The choices for Level Type are:
N: Normal Level.
L: Lookup Level. This level must be preceded by an N Level.
D: Detail Level. This level is associated with a grid.
DA: Detail (application loaded). If the application uses DetailLoad to load the
grid, the Solomon kernel automatically handles the update. If the application does
not use DetailLoad, the application must handle all updates for this level manually.
C: Constant Level. Used when no database navigation is necessary for this level.
The same record is always displayed. This is checked by VB Code Inspector.
Although you can have multiple D and DA levels, they should appear last in the
Level property unless the levels beyond the D or DA levels are intended to be nonnavigable. This is optionally checked by VB Code Inspector, by selecting the
Warning Option Order of Levels specified in Update Levels property.
Introduction
SetAddr calls
A SetAddr call must be made for every record referenced by a control on the screen.
This is checked by VB Code Inspector.
Additional records that are accessed by the application do not require a SetAddr call.
However, making a SetAddr call for the record, makes that record easily available for
customization. Also, the use of the SetAddr call properly initializes the buffer to blanks
for strings (instead of nulls). There is, however, a possible performance tradeoff in
making too many SetAddr calls.
It is important for the second parameter of the SetAddr call (buffername) to be a b
followed by the full table name. However, it is often necessary to retrieve to separate
instances of the same table. When it is necessary to create a second buffer for the
additional instance, a number can be placed at the end of the btablename (that is,
bcustomer1). When this guideline is not followed, errors may occur in the application.
Grids
For grid functionality, it is important for all controls contained within the grid as well
as the grid control itself, to be contained within the frame (or whatever container is
selected). This can be tested by attempting to move a control outside the frame that
surrounds the grid data (in design mode).
If the control cannot be moved outside the frame, it is contained within the frame. If it
can be moved outside the frame, these controls must be selected, then Cut, then focus
on the frame and Paste. Keep in mind that this operation will probably alter the
tabindex properties and they will need to be reset.
The maximum number of grids per application is 10. This is checked by VB Code
Inspector. The maximum number of tables associated with a single grid is 16.
No visual controls within a grid container should be placed outside the visual
boundaries of that container. This approach makes controls visible in Grid view, but
not in Form view. This is optionally checked by VB Code Inspector, if the Warning
Option Visible Controls outside the Grid container is selected.
10
Memory arrays
When looping through memory arrays in code, it is important that you preserve your
original position in the array and reset back to that position when you are finished with
the loop. You do this with the MgetRowNum, and MsetRow functions. Failure to do
this causes the application to display several errors about the memory array not
matching the grid. (that is, bulletproof 10061, 11008, 20007). It can also cause the CutCopy-Paste function to fail.
An application may have an unlimited number of memory arrays. The maximum
number of keys allowed for a single memory array is 5.
Messages
The Solomon Message APIs should be used in all cases. Transaction Import is unable
to recognize and respond to VB message calls.
Messages should never be hard-coded in an application. Messages.csv or an equivalent
method should be used, so that the messages may be translated if necessary.
Avoid concatenating multiple messages. The syntax of many languages is different, so
translation of the individual pieces may be difficult.
For process status messages, labels are often placed on the form with their visible
property set to False. This way, the application can reference the control.caption
property to display the message.
Never display a messages during an open transaction. A transaction is open after a
TranBeg has been called and inside the Update1_Update or Update1_Delete events.
NEVER call TranEnd from within the Update1_Update event to allow a message to be
displayed.
Status()
Make status calls only in process applications. In these cases, the Solomon kernel does
not set TranBeg automatically and will not interfere with these calls.
Never make a status call in the Update1_Update Event. In this case, the Solomon
kernel has already started a transaction. Placing a status call here would cause record or
page locking errors.
Key fields
All Normal and Lookup levels should have at least one key field. This is optionally
checked by VB Code Inspector if the Warning Option No Key field defined for
Navigation or Lookup level is selected.
Introduction
11
All key fields (,k) should have their BlankErr properties set to True for D or DA
levels. This is checked by VB Code Inspector.
The last key field for every level, must have its PV or DBNav property populated. This
is optionally checked by VB Code Inspector if the Warning Option No PV or
DBNAV property on last key field of Navigation level is selected.
The maximum number of key fields per level is 5. This is checked by VB Code
Inspector.
Unbound controls
To define unbound controls place values in the Field Offset, Field Type, and Field
Length properties (on the Fieldname Property page).
Even if the field is NOT unbound (that is, the table exists in the database), but
values exist in the Field Offset, Field Type, or Field Length property, VB Code
Inspector attempts to make the calculation. However, the Solomon kernel knows
that the field is not unbound and these values are not used. This is checked by VB
Code Inspector.
12
Third-party controls
Third-party controls have limited properties that may be customized. They are not,
however, accessed by templating, which raises issues with application server as well,
because templates are the way that application server fills the screen that is to be
processed.
In this case, data keyed into third party controls is not captured in the template and
therefore, is unavailable to the application server process. This is optionally checked by
VB Code Inspector if the Warning Option Third Party controls used in the
Application has been selected.
Maximum size of one description line for VB Tools Combo box is 81.
Place the Toolbar control in that frame. The instance of the Toolbar control MUST
be named MenuBars.
There is code in SWIM.BAS that repositions the Frame and interacts with the Toolbar
control. For these references to work correctly, the names must match.
The Literals, or captions for the items on the Toolbar, can be customized only by
recompiling the ToolBarenu.dll (source is part of the Localization Toolkit).
Introduction
13
Database Considerations
Cursors
The maximum number of cursors available to an application is 50; the maximum
number of cursors available to customizations is 30.
If a SQLCursor or SQLCursorEX call is not made for a cursor, it is automatically
declared as SQLReadOnly and is not freed automatically.
SQLCursorEX is the preferred API call. It allows the application to specify additional
parameters that optimize data access for SQL Server. This is optionally checked by VB
Code Inspector if the Warning option Use of SQLCursor vs SQLCursorEX in the
application is selected.
Indexes
All Solomon database tables require a unique index, which is the full table name with a
0 appended. (for example, Customer0).
The maximum number of fields in an index is 8.
14
15
Where Available
Description
ApplSetParmValue
VB Tools, BSL
CallApplic
VB Tools
CallApplicWait
VB Tools
Launch
BSL
ApplGetParmValue
VB Tools, BSL
ApplGetParms
VB Tools, BSL
ApplGetReturnParms
VB Tools
These functions allow parameters to be processed separately for VB Tools, BSL, and
TI (Transaction Import) applications, and allow an application to access any parameter
type from any other VB Tools, BSL, or TI application.
After an application adds parameters, a temporary, uniquely named parameter file
(with a .PRM extension) is automatically created by the Solomon kernel. This file
contains the parameter values that are to be passed to the receiving program.
16
17
Retrieving Parameters
Use ApplGetParmValue in the Load event of an application to retrieve values from
the parameter file passed from another application. ApplGetParmValue retrieves the
section, entry, and value that was placed in the parameter file.
The following examples show how to retrieve parameter values from a parameter file:
BSL
'Code for Form1_Display event of 08.260 Customer screen
Dim PassedParm As String
PassedParm = ApplGetParmValue("[MyScreen]", "CustomerId")
If Trim$(PassedParm) <> "" Then
'Set field value only if parameter is not blank
serr1 = SetObjectValue("ccustid", PassedParm)
End If
VB Tools
'Code for Form1_Load event of 08.260 Customer screen
Dim PassedParm As String
PassedParm = ApplGetParmValue("[MyScreen]", "CustomerId")
If Trim$(PassedParm) <> "" Then
'Set field value only if parameter is not blank
bCustomer.CustId = PassedParm
Call DispField(ccustid)
End If
18
Type
Description
Form1
Form
NEW_FORM.FRM
Form
Update
Control
SAFDesigner
Control
SAFNewFrame
(VB Frame Control)
Control
SAFNewTab
(VB SSTab Control)
Control
SAFContainer
Control
SolomonVBTApp
Class module
All of the controls in the preceding table must be included on every form in the VB
Tools project. Note that these controls are added to a project automatically by running
VB Code Inspector, and in this case their properties should not be modified.
All of the required components are contained in the VB Tools project template file,
VBTProject.vbp.
19
Do not modify the settings created by the VB Code Inspector for the required
components previously listed.
Do not create code for the Click event for a Tab control.
Ensure that control names are unique across the project (including subforms).
Ensure that all controls within a grid frame are within the coordinate boundaries of
the frame by following these property rules:
control.Top > 0
control.Left > 0
Ensure that required property settings are not violated by evaluating conditions
before using SetProps in code to modify property settings.
Ensure that all controls within a grid frame have contiguous values for their
Tabindex properties.
Form
Label
Frame
SSTab
CommandButton
20
SAFMaskText
SAFUpdate
SAFInteger
SAFDate
SAFFloat
SAFCombo
SAFCheck
SAFOption
SAFGrid
Left
Top
Height
Width
Enabled
Visible
Controls bound to Table.Field entries from the database are unavailable for
insertion by the Insert Object Wizard in Customization Manager. For example, if a
table contains 10 fields, and controls on your application are bound to 8 of these
fields, only the 2 unbound fields are available to the Insert Object Wizard. In the
wizard, the user will see only tables that are bound programmatically through code
with a SetAddr( ) statement.
All controls that are secure at the application level cannot be unsecured through
Customization Manager. Customization Manager can only be more restrictive, not
less restrictive. Modifications to the properties of secured controls are allowed in
Customization Mode, but with the following restrictions:
21
Changes to the Minimum and Maximum values for a range can only narrow
the range.
List items cannot be added to combo box or text box controls if data already
exists in the List or PV property for these controls.
A hidden control that should not be customized by the user should be positioned to
the far left of the form so it does not appear in Customization Mode. For example,
set the controls Left property to a large negative number such as -2000. (You
cannot use this method to position a control within a grid frame.)
Run VB Code Inspector on every build of your application and correct all errors
found. Most of the errors that Code Inspector is designed to detect are those that
cause subsequent errors when an end user attempts to customize the application.
Keeping VB Code Inspector visible in the VB Add-ins menu ensures that you are
automatically prompted to run Code Inspector when creating an executable.
Testing Applications
Test your applications for Customization Manager compatibility. Load each form in
your application and select Customize Mode from the Solomon parent toolbar. Grab
handles should appear around the form and no error message should be displayed.
All third-party controls should be tested in Customize Mode to determine if they can be
customized without error. Select each control in Customize Mode and press F4 to
display the property window. The property window should display the limited property
entries as described earlier (Left, Top, Height, Width, Enabled, and Visible).
22
23
[Scenarios] Section
The [Scenarios] section lists all possible scenarios that can be selected from Database
Maintenance (98.290.000). Several scenarios may exist in this section to describe the
available database scenarios. Each item must be of the format
Scenario#=Descriptive Text
where # is a number and Descriptive Text is a short description of what the scenario
is. The maximum length of the Descriptive Text is 128 characters.
The maximum number of scenarios that can be listed within this section is limited only
by the 64K data limit of the Windows ListBox control, which gets populated with
items from this [Scenarios] section.
The Scenario# items must start with Scenario1 and increment by 1 for each scenario.
For example the following is a valid [Scenarios] section
[Scenarios]
Scenario1 = Empty Company Databases
Scenario2 = Demo Premier Databases
Scenario3 = Demo Select Databases
24
[Scenario#] Sections
Each scenario listed in the [Scenarios] section must have a corresponding section
within the same configuration file. Each individual [Scenario#] section contains data
specific to each system and application database to be created. Refer to the following
example when reading the explanation of how this section works:
[Scenarios]
Scenario1 = Empty Company Databases
Scenario2 = Demo Premier Databases
[Scenario1]
SysName = NewSystem
SysSize = 10
SysImport = empty database\system\import.lst
AppNames = NewApp
AppSizes=40
AppImports=empty database\application\Import.lst
[Scenario2]
SysName = DemoPremierSystem
SysSize = 10
SysImport = demo database\premier\system\import.lst
AppNames = DemoPremierApp10;DemoPremierApp60
AppSizes=40;50
AppImports=demo database\premier\appdb10\import.lst;demo
database\premier\appdb60\import.lst
Six key names that may be specified within each Scenario# section. Three of the keys
contain information about the system database, and three of them contain information
about the application database. These keys specify default values and may be
overridden by using Advanced on the Create Databases tab of Database Maintenance
(98.290.00).
25
SysName
The SysName key indicates the default database name of the system database. This
name must conform to MS SQL Server 7.0 Database Naming Conventions.
If a database with this name already exists on the destination SQL Server, and no
application databases are specified for this scenario when the Create button is clicked,
an error message will be displayed that indicates the database exists. If a database with
this name already exists on the destination SQL Server, and at least one application
database is specified to be created for this scenario, then only the application databases
will be created, and they will be associated with the system database specified here. If
a database does not exist on the destination SQL Server with this same name, then it
will be created.
SysSize
The SysSize key indicates the initial size in MB of the system database when it is
created.
SysImport
The SysImport key specifies a relative path and filename of an import file to use when
importing data into the system database created with this scenario. The import file
specifies the name of the table to import data into, the name of the file that contains the
data, and the format of the data. The path specified is relative to the path of the
configuration file in which this setting is specified. The import file must exist in the
same directory as the import.lst file specified in this key.
For example, assume a configuration file is located in c:\program files\Solomon\db.
Then the full path and file name of the SysImport key value under Scenario2 in the
example would be c:\program files\Solomon\db\demo
database\premier\system\import.lst.
Below is an example of an import file that could be used here:
Pvrec, pvrec.bcp, /n
Pvrec, pvrec.bcp, /n
Registitem, registit.csv
Registitem, registit.csv
For more information on the import file format and BCP options, see Import File
Format.
AppNames
The AppNames key indicates the default database names of the application databases
to be created. These names must conform to MS SQL Server 7.0 Database Naming
Conventions and must be separated by semicolons if more than one application
database name is specified. There must be a corresponding size specified in the
AppSizes key for each database name specified.
If a database with this name already exists on the destination SQL Server when the
Create button is clicked, an error message will be written to the dbbuild.log file that
indicates the database exists.
26
AppSizes
The AppSizes key indicates the initial size in MB of the application databases when
they are created. Each size corresponds to the database names specified in the
AppNames key, and the sizes must be separated by a semicolon.
AppImports
The AppImports key specifies a relative path and filename of an import file to use
when importing data into the application databases created with this scenario. The path
specified is relative to the path of the configuration file in which this setting is
specified. If multiple import files are specified, they must be separated by a semicolon
and they correspond to the database names specified in the AppNames key. The entire
length of values specified in the AppImports key is limited by 128 characters.
2.
3.
4.
5.
6.
27
tables
The tables key specifies the location and name of files that contain Create Table
statements for the databases. Multiple files can be specified and must be separated by a
semicolon. The length of the key value cannot exceed 128 characters, including the
semicolons.
A relative path may be specified for each file listed. The path will be relative to the
location of the configuration file or the path specified in the scriptpath section if it
exists. Absolute pathnames may not be specified.
28
indexes
The indexes key specifies the location and name of files that contain Create Index
statements for the databases. Multiple files can be specified and must be separated by
semicolons. The length of the key value cannot exceed 128 characters, including the
semicolons.
A relative path may be specified for each file listed. The path will be relative to the
location of the configuration file or the path specified in the scriptpath setting if it
exists. Absolute pathnames may not be specified.
procedures
The procedures key specifies the location and name of files that contain Create
Procedure statements for the application databases. Multiple files can be specified
and must be separated by semicolons. The length of the key value cannot exceed 128
characters, including the semicolons.
A relative path may be specified for each file listed. The path will be relative to the
location of the configuration file or the path specified in the scriptpath setting if it
exists. Absolute pathnames may not be specified.
views
The views key specifies the location and name of files that contain Create View
statements for the application databases. Multiple files can be specified and must be
separated by a semicolon. The length of the key value cannot exceed 128 characters,
including the semicolons.
A relative path may be specified for each file listed. The path will be relative to the
location of the configuration file or the path specified in the scriptpath setting if it
exists. Absolute pathnames may not be specified.
triggers
The triggers key specifies the location and name of files that contain Create Trigger
statements for the databases. Multiple files can be specified and must be separated with
a semicolon. The length of the key value cannot exceed 4,096 characters, including the
semicolons. A relative path may be specified for each file listed. The path will be
relative to the location of the configuration file or the path specified in the scriptpath
section if it exists. Absolute pathnames do not work; paths must be relative.
constraints
The constraints key specifies the location and name of files that contain Alter
TableAdd Constraint statements for the databases. Multiple files can be specified
and must be separated with a semicolon. The length of the key value cannot exceed
4,096 characters, including the semicolons. A relative path may be specified for each
file listed. The path will be relative to the location of the configuration file or the path
specified in the scriptpath section if it exists. Absolute pathnames did not work. paths
must be relative.
29
defaults
The defaults key specifies the location and name of files that contain Create Default
statements for the databases. Multiple files can be specified and must be separated with
a semicolon. The length of the key value cannot exceed 4,096 characters, including the
semicolons. A relative path may be specified for each file listed. The path will be
relative to the location of the configuration file or the path specified in the scriptpath
section if it exists. Absolute pathnames do not work; paths must be relative.
rules
The rules key specifies the location and name of files that contain Create Rule
statements for the databases. Multiple files can be specified and must be separated with
a semicolon. The length of the key value cannot exceed 4,096 characters, including the
semicolons. A relative path may be specified for each file listed. The path will be
relative to the location of the configuration file or the path specified in the scriptpath
section if it exists. Absolute pathnames do not work; paths must be relative.
import
The import key specifies the location and name of the import file or files that hold
names of tables and corresponding data files. The import files need to be located in the
directory specified in the scriptpath setting in the configuration file or, if scriptpath is
not specified, in the same directory as the file specified in the import key.
The .csv file specified needs to specify data for ALL fields in the table.
In the example under [MSSQL System Scripts] and [MSSQL Applications Scripts]
on page 26, import.lst is the file that contains the import information. Here is an
example of import.lst:
UserRec, userrec.csv
UserGrp, usergrp.csv, /n
RegistItem, registit.csv, /c /t# /r\n
APDoc, APDoc.csv, /c /t; /r\t /E
The first line indicates that userrec.csv is a comma-delimited ASCII file with carriage
return/linefeed characters as the row delimiter and a comma as the column delimiter.
This file contains the data that will be imported into the UserRec table.
The second line indicates that the usergrp.csv file is in Microsoft SQL Servers native
BCP format and contains the data to import into the UserGrp Table.
The third line indicates that the registit.csv file is in ASCII format, and uses the #
character as the column delimiter and carriage return/linefeed characters as the row
delimiter. This file contains the data to import into the RegistItem table.
The fourth line indicates that the apdoc.csv is in ASCII format, the columns are
delimited by a comma and the rows are delimited by a tab character, and we want to
explicitly set any identity fields to a specific value. This file contains the data to import
into the APDoc table.
For more information on the import file format and BCP options, see Import File
Format on page 34.
30
scriptpath
The scriptpath key indicates an absolute path location to the directory that holds all
the script files. The path specified here will also become the location to which all paths
specified in the tables, indexes, views, and procedures keys are relative.
The script files specified in the configuration file must be Microsoft SQL Server
Transact-SQL Create statements. The script file specified for the tables key should
contain T-SQL formatted Create Table statements. The script file specified for the
indexes key should contain T-SQL formatted Create Index statements. The script file
specified for the procedures key should contain T-SQL formatted Create Procedure
statements. The script file specified for the views key should contain T-SQL formatted
Create View statements.
31
[Update Scenario1]
Apptables=common\Application\MSAppADBTables.SQL;
common\Application\ADG_Tables.sql
Appindexes=common\Application\MSAppADBIndexes.SQL;
common\Application\ADG_Indexes.sql
Appprocedures=common\Application\MSAppADBProcs.SQL;
common\Application\ADG_Procs.sql
Appviews = Appimport=common\Application\Import.lst
Apptriggers=common\Application\MSAppDBTriggers.SQL
Systables=common\system\0MSCRT.SQL;common\system\
MSAppSDBTables.sql
Sysindexes=common\system\1MSNDX.SQL;common\system\MSAppSDBIndexe
s.sql
Sysprocedures=common\system\SYPROCS.SQL;common\system\MSAppSDBPr
ocs.sql
Sysviews = Sysimport=common\system\Import.lst
Sysconstraints=common\system\SysDBConstraints.sql
These keys specify the location and name of files that contain SQL statements used to
perform schema updates and imports of data. The length of the key value for each of
these keys cannot exceed 4,096 characters, including the semicolons.
When a specific update scenario is selected on the Update tab of Database
Maintenance (98.290.000), all the scripts specified in the following sections are
executed for that specific update scenario. These scripts are applied to the system
database and all selected application databases. Multiple application databases may be
selected from the Update tab.
apptables
The apptables key specifies the location and name of files that contain Create Table
statements for the application databases. See the description of the Tables key in the
[MSSQL Applications Scripts] and [MSSQL System Scripts] section for a description
of this key. The same rules and limits apply here.
32
appindexes
The appindexes key specifies the location and name of files that contain Create Index
statements for the application databases. See the description of the Indexes key in the
[MSSQL Applications Scripts] and [MSSQL System Scripts] section for a description
of this key. The same rules and limits apply here.
appprocedures
The appprocedures key specifies the location and name of files that contain Create
Procedure statements for the application databases. See the description of the
Procedures key in the [MSSQL Applications Scripts] and [MSSQL System Scripts]
section for a description of this key. The same rules and limits apply here.
appviews
The appviews key specifies the location and name of files that contain Create View
statements for the application databases. See the description of the Views key in the
[MSSQL Applications Scripts] and [MSSQL System Scripts] section for a description
of this key. The same rules and limits apply here.
appimport
The appimport key specifies the location and name of the file that holds names of
tables and data files to import into. See the description of the Import key in the
[MSSQL Applications Scripts] and [MSSQL System Scripts] section for a description
of this key. The same rules and limits apply here.
apptriggers
The apptriggers key specifies the location and name of files that contain Create
Trigger statements for the application databases. See the description of the Triggers
key in the [MSSQL Applications Scripts] and [MSSQL System Scripts] section for a
description of this key. The same rules and limits apply here.
appconstraints
The appconstraints key specifies the location and name of files that contain Alter
TableAdd Constraint statements for the application databases. See the description of
the Constraints key in the [MSSQL Applications Scripts] and [MSSQL System Scripts]
section for a description of this key. The same rules and limits apply here.
appdefaults
The appdefaults key specifies the location and name of files that contain Create
Default statements for the application databases. See the description of the Defaults
key in the [MSSQL Applications Scripts] and [MSSQL System Scripts] section for a
description of this key. The same rules and limits apply here.
33
apprules
The apprules key specifies the location and name of files that contain Create Rule
statements for the application databases. See the description of the Rules key in the
[MSSQL Applications Scripts] and [MSSQL System Scripts] section for a description
of this key. The same rules and limits apply here.
systables
The systables key specifies the location and name of files that contain Create Table
statements for the system databases. See the description of the Tables key in the
[MSSQL Applications Scripts] and [MSSQL System Scripts] section for a description
of this key. The same rules and limits apply here.
sysindexes
The sysindexes key specifies the location and name of files that contain Create Index
statements for the system databases. See the description of the Indexes key in the
[MSSQL Applications Scripts] and [MSSQL System Scripts] section for a description
of this key. The same rules and limits apply here.
sysprocedures
The sysprocedures key specifies the location and name of files that contain Create
Procedure statements for the system databases. See the description of the Procedures
key in the [MSSQL Applications Scripts] and [MSSQL System Scripts] section for a
description of this key. The same rules and limits apply here.
sysviews
The sysviews key specifies the location and name of files that contain Create View
statements for the system databases. See the description of the Views key in the
[MSSQL Applications Scripts] and [MSSQL System Scripts] section for a description
of this key. The same rules and limits apply here.
sysimport
The sysimport key specifies the location and name of the file that holds names of the
tables and data files into which to import. Please see the description of the Import key
in the [MSSQL Applications Scripts] and [MSSQL System Scripts] section for a
description of this key. The same rules and limits apply here.
systriggers
The systriggers key specifies the location and name of files that contain Create Trigger
statements for the system databases. See the description of the Triggers key in the
[MSSQL Applications Scripts] and [MSSQL System Scripts] section for a description
of this key. The same rules and limits apply here.
34
sysconstraints
The sysconstraints key specifies the location and name of files that contain Alter
TableAdd Constraint statements for the system databases. See the description of the
Constraints key in the [MSSQL Applications Scripts] and [MSSQL System Scripts]
section for a description of this key. The same rules and limits apply here.
sysdefaults
The sysdefaults key specifies the location and name of files that contain Create
Default statements for the system databases. See the description of the Defaults key in
the [MSSQL Applications Scripts] and [MSSQL System Scripts] section for a
description of this key. The same rules and limits apply here.
sysrules
The sysrules key is used to specify the location and name of files that contain Create
Rule statements for the system databases. Please see the description of the Rules key in
the [MSSQL Applications Scripts] and [MSSQL System Scripts] section for a
description of this key. The same rules and limits apply here.
/f <format file>: Specifies a file that indicates to SQL Server the format of the
data file you are using. This file must reside in the directory specified in the
scriptpath setting in the configuration file or, if scriptpath is not specified, in the
same directory as the configuration file.
/c: Tells SQL Server to use ASCII format. If /c is used, you must also specify the
following flags:
If neither of these options is specified, the default column delimiter is the comma
and the default row delimiter is the carriage return/linefeed.
/E: Indicates to SQL Server that you want to set identity fields. If you do not
specify this option and your table has an identity field, the value of the field will
be incremented from the last identity value used in that table.
Note: The E must be an uppercase E.
35
36
37
38
The caption of the WinHelp 4.0 Help Topics window is static text. Solomon
does not support automatic or programmatic updating of this caption.
Each Independent Software Vendor (ISV) Help system can have one or more Help
files.
Each ISV Help system must have one table of contents (.CNT) file that will
control how the contents of the Help files for the product is logically presented to
the viewer.
Each ISV product should have one or more books at the root of the contents file.
Each book should contain at least one topic and can optionally contain other
books.
You cannot add books or topics to any book provided by Microsoft Business
Solutions.
Microsoft Business Solutions does not support the modification of a book name
without changing the name of its corresponding Help file.
39
In the Project Properties dialog for your application, add the Help File Name of
the Help file on the General tab. Do not include path information with the name.
2.
ApplInit() now sets the Visual Basic object property App.HelpFile by looking up
the Help file path and appending the Help file name you entered on the Project
Properties screen. ApplInit() determines this path by appending \Help to the
Parent Directory value stored in the system registry at
HKEY_LOCAL_MACHINE\\Software\Solomon\Solomon IV Tools For
Visual Basic.
3.
4.
5.
Enter a context ID number for the Help topic associated with the control.
6.
40
41
Changes in internal formats and memory layouts used by VB 5.0, most notably the
use of Universal Character Set for internal storage of character strings and the
changes in the memory alignment of elements in User-Defined Data Types
(UDTs).
Solomon provides Application Translator to help you migrate your VB 3.0 and 4.0
files to VB 5.0. Application Translator is a Solomon-provided VB add-in utility that is
run on each VB 3.0 or 4.0 project. It uses the VB3 or VB4 project file as input to create
a converted VB5 project file. All files in the source project, including .vbp, .frm and
.frx files, as necessary, are created in the new destination project. Solomon 16-bit VB
Tools Controls are re-assigned to Solomon 32-bit VB Tools Controls, and all VB
Tools-provided functions calls are converted from 16-bit to 32-bit.
Application Translator makes the following changes to the new project file:
Controls and references that are no longer used by 32-bit VB Tools are removed.
New 32-bit controls and references used by 32-bit VB Tools are added.
Changes are made in the .frm files to specify the values of the properties as
appropriate for the 32-bit controls.
Changes are made to the source code contained in .frm files as appropriate for the
32-bit controls and 32-bit functions.
Changes are made to the source code in .bas, .dh and other module files as
appropriate for the 32-bit functions.
42
Application Translator changes VB source code lines containing the LEN function
to use the LENB function in instances in which the single parameter of LEN is a
User-Defined Types (UDT).
Instances in which LEN is changed to LENB are:
SetAddr
DBNavFetch, PVChkFetch
DetailSetup, DetailSetupExtend
MOpen
Application Translator changes the name of the NEW event in the Update control
to NEWLEVEL. The old code from the old NEW event is moved unchanged to
the new NEWLEVEL event.
43
Currently, there are no other changes made to lines of VB source code in any .frm
or VB module files by Application Translator. Although it is not impossible, it is
unlikely that Application Translator will ever make any other source code changes
in the future.
Application Translator does just as good a job at translating non-VB Tools Third-Party
Controls (if you have used them) as VB 5.0 would do, plus it provides significant
additional conversion features that the standard VB5 conversion does not have.
For VBX controls, Application Translator reads the standard VB.ini file and looks in
the [VBX Conversions32] section. If the Third-Party control you use has a 32-bit
replacement and has properly registered the 16-bit VBX and the 32-bit replacement
OCX in the [VBX Conversions32] section of the VB.ini file, the Application
Translator automatically translates the VBX to its 32-bit OCX version.
This approach is consistent with standard VB 5.0 behavior, but you will still possibly
need to make adjustments for any properties that went away between the 16-bit VBX
and the 32-bit OCX replacement.
To make Application Translator aware of any Third-Party controls, you need to add an
entry to the Solomon VBTrans.ini file for each 16-bit VBX name, to specify the new
32-bit OCX name in the [VBTranslator-Controls] section.
44
Name
Description
SAFUpdate
SAFMaskedText
SAFInteger
SAFDate
SAFFloat
SAFCombo
SAFCheck
SAFOption
SAFGrid
SAFContainer
SAFDesigner
The same field from the database will frequently appear in several different programs
throughout the Solomon product. This means that the same control will be needed, and
many of the properties for those controls should be set exactly the same way in each
program where the same database field is being accessed.
45
5.
Enter the SQL Server Name, User ID, and Password for the server that holds the
application database with the VB Tools data.
6.
46
Click the Connect button. The Select Controls tab will appear:
8.
In Record Name, select the table from which you wish to add a control. You can
use the button to the right of the control to open a list of tables. To select one of
the tables, click on it, then press the ENTER key.
9.
Select the control(s) that you wish to add from the list box on the left and use the
arrow buttons to move the controls to the list box on the right.
47
The Solomon kernel uses the controls in the container object to determine what
columns should be included in the spreadsheet (grid view), how the columns should be
formatted, and what buffer variables the columns should be bound to.
Because of the form view functionality, it is important to place the data controls for
the detail level in an esthetically pleasing way.
Level Property of a buffer variable Tells the Solomon kernel that it should use
that buffer variable to store records retrieved from the primary table for the level.
If the Solomon kernel refreshes the data associated with a level, then redisplay
the information in all controls with the same level.
If a CHK event fires on a control, then set a dirty flag for the level
associated with the control to indicate that the data in that level has been
updated.
48
These controls
are all Solomon
data controls
When you manually paste a text control, it is important to match the data types of the
data, the buffer variable, and the text control that you use.
49
2.
In the Project Explorer window Forms folder, double left click on a Form object to
display its design window.
3.
4.
In the Toolbox window, double-click on the Solomon control you want to add.
5.
After the control appears on the Form design view window, reposition and resize
the control as needed.
50
When you install the Tools for Visual Basic, the Definitions for almost all of the
existing Solomon tables will be installed and be visible in this screen.
When adding new tables to Solomon database, there is one naming convention
suggested by Microsoft Business SolutionsSolomon will never begin any of the
standard product table names with an X. Therefore, if third-party developers always
create their tables beginning with an X, they can be sure that future updates of the
Solomon product will not cause a naming conflict. (Note that there is no formal
convention to prevent multiple third-party developers from creating tables with the
same names.)
Note: Although the X is the only explicitly stated naming convention for tables, there
are some implicit restrictions. These restrictions result from the fact that Solomon uses
the name assigned to tables as the names for variables in Tools for Visual Basic
programs. This means that any naming restrictions that apply to VB variables must also
be followed for Solomon tables. Some of these restrictions are as follows:
Table names should not end in a number (because of the Solomon kernels
implementation of its SetAddr function).
2.
3.
4.
In the Record Name field, type the name of the table you want to create.
5.
6.
In the Module field, select the module to which the table applies, or <none> if it
applies to multiple modules.
7.
51
52
The standard controls and properties of the controls that should be used when
creating a Tools for Visual Basic program that accesses the field
As with the table names, when you install the Tools for Visual Basic, the definitions
for almost all of the existing Solomon fields will be installed and can be accessed via
this program.
Also like table names, field names are used within Tools for Visual Basic programs as
variable names. Therefore, just like table names, field names must adhere to standard
variable naming restrictions.
53
Note: Though the standard fields can be accessed in this program, the physical structure
of the standard Solomon tables (i.e., field data types, field sizes, number and order of
fields, etc.) should NEVER be altered! For a Tools for Visual Basic program to access
a record from the database, a variable that has the exact same structure as the record
being selected must be defined and created at the time the program is written. This is
true for all of the standard Solomon programs as well as any programs written by third
parties. Because Solomon almost always retrieves records by performing SELECT *
FROM Table, any changes to the structure of a table would cause records from that
table to no longer properly fit in the variables that were created to hold those records.
>
2.
In the Record Name field, type the name of the table that will contain the field.
3.
In the Field Name field, type the name of the new field.
4.
Fill in the remaining fields as needed to define the properties of the new field.
54
Creating Tables
The steps in creating a table are:
1.
2.
3.
4.
5.
Standard Solomon file extensions are all recognized by a Solomon utility program
called Database Update which can read these files and update the current database
using the information found in them. See Solomon Standard File Extensions for
more information.
CRT This extension is used for SQL script files that contain CREATE TABLE
statements.
CRX This extension is used for SQL script files that contain CREATE INDEX
statements.
CRP This extension is used for SQL script files that contain CREATE
PROCEDURE statements.
CRU This extension is used for SQL script files that can contain any kind of
SQL statements, including CREATE TABLE, INDEX, and PROCEDURE
statements.
CSV This extension is used either for Possible Value window declarations or
for comma delimited ASCII data files.
IMP This extension is used for SQL script files that contain INSERT INTO
statements that can be used to import the data in CSV files.
DH This extension is used for VB module files that contain user defined type
definition and global variable declarations for the buffers that hold records from
the database.
GLB This extension is used for VB module files that contain global variable
declarations for things like cursor and memory array handles.
CRT, CRX, CRP, CRU, CSV and IMP file extensions are all recognized by a Solomon
utility program called Database Update which can read these files and update the
current database using the information found in them.
55
A CRT extension file which will contain the SQL CREATE TABLE statement
required to create the table in a database
A DH extension file which will contain a VB UDT declaration and two global
declarations for variables of that type
These two files are created by the same program, using the same information, at the
same time. This ensures that, if the CRT file is used to create the table in the database,
then the UDT will have the exact same structure as the table.
56
>
To generate a SQL CREATE TABLE script file and DH file using Generate
Schema (93.400.00)
1.
2.
3.
4.
5.
6.
7.
8.
9.
2.
3.
In the DB drop down box of the ISQLW, Query Window, Toolbar, select your
application database.
2.
3.
4.
5.
6.
7.
8.
9.
57
Which of these two sets the procedure will return is determined by whether or not
wildcards are passed as parameters to the stored procedure. Here are some guidelines:
The procedure should be a Select statement that selects every field from the table.
Every field from the unique index of the table should be included as a condition in
the Where clause.
At least one of the Where clause conditions, on one or more of the index fields,
should be compared to a replacement parameter.
If a wildcard is passed to at least the last parameter, then the statement should
return every record in the table.
If actual values are passed, the statement should return one and only one record.
There should be an Ordered By clause that matches an index of the table. Usually
it will match the unique index.
58
Checking Code
The VB (Visual Basic) Code Inspector is a VB Add-In provided by Microsoft Business
Solutions to inspect Visual Basic projects using the Tools for Visual Basic controls
and functions. It enables you to find and fix certain well-defined problems in your
application code. Code Inspector is installed as part of the Tools for Visual Basic
module.
59
Code Inspector searches through the project for any Tools for Visual Basic controls
that are unbound: any VB Tools control that references a field (via the controls
FieldName property) that has been manually specified. When Code Inspector
performs a check, it looks for Tools for Visual Basic controls having non-zero values
in any one of the following Property Page fields:
FieldName
DBNav
Default
PV
(These properties all contain appropriate Property Page fields to allow definition of
user-defined types.)
A control is considered unbound if one or more of the following parameter values of
the FieldName property is non-zero:
Declare Length
Declare Type
Field Offset Value
If an unbound control is found, Code Inspector uses the value in the Struct.FieldName
field on the FieldName Property Page to look up meta-data about that field from
within a VB project. Once Code Inspector finds the meta-data, it determines if the databinding values on the FieldName Property Page are accurate. Code Inspector attempts
to calculate the correct length and Field Offset Value for the field, using
information in the FieldName Struct.FieldName parameter value and the information
referenced in the parameters of the corresponding SetAddr call.
If the data binding values that Code Inspector calculates are incorrect (different from
those in the FieldName property), Code Inspector gives you the option of having it
automatically resolve the problem by programmatically entering the correct values. If
Code Inspector is unable to locate meta-data about the Struct.FieldName, it notifies
you of this fact but does not alter code.
Note: If a particular field is bound to an element of a single-dimensional array, Code
Inspector expects the Struct.FieldName field on the FieldName Property Page to be
formatted as follows: MyStructure.MyField(1). In other words, it expects the index of
the element to which the control is bound to be enclosed within parenthesis (as
opposed to something like MyStructure.MyField01 with no parentheses).
Currently, no other changes are made to any lines of VB source code in any .FRM or
VB module files by Code Inspector. However, in the future, Code Inspector may be
enhanced to check other source code errors or control property errors and may prompt
when additional errors are found.
60
SAFDes.ocx
SAFCont.ocx
TABCTL32.ocx
Code Inspector also verifies that four controls are present on each form of the project
and prompts to add them if they are missing. These controls are required by Tools for
Visual Basic and are also used by Customization Manager, specifically Customization
Managers Insert Object Wizard, to create new objects at runtime. These controls are:
SAFDesigner
SAFContainer
SAFNewTab
SAFNewFrame
If Code Inspector determines that any of these controls are missing, it provides the
option to resolve the problem automatically.
The SAFContainer and SAFDesigner controls are provided by the SAFCont.ocx and
SAFDes.ocx ActiveX component files respectively. They are installed and registered
during the VB Tools installation process.
Code Inspector verifies that the current application project it is running contains a
reference to the SAFDes.ocx and SAFCont.ocx ActiveX components and also verifies
that all application form files contain an instance of these controls. The following are
the specific tests performed:
Each occurrence of SAFCont.ocx has the following entry in the project file:
Object = {67C66D63-8B90-11D1-A413-00609731B708}#1.0#0; SAFCont.ocx
Each occurrence of a form has the following entry in the top of the form file:
Object = "{67C66D63-8B90-11D1-A413-00609731B708}#1.0#0"; "SAFCont.ocx"
Begin SAFCONTAINERLib.SAFContainer SAFContainer1
Index
Left
Visible
End
= 0
= -20000
= 0 'False
61
Each occurrence of SAFDes.ocx has the following entry in the project file:
Object={79F2369D-9E3F-11D1-A45F-0060080A803B}#7.1#0; SAFDes.ocx
Each occurrence of a form has the following entry in the top of the
form file:
Object = "{79F2369D-9E3F-11D1-A45F-0060080A803B}#7.1#0"; "SAFDes.ocx"
Begin CustomizationManager.SAFDesigner SAFDesigner1
Left
= -20000
Visible
= 0 'False
End
Code Inspector makes no change to the application project and forms if the
SAFDes.ocx and SAFCont.ocx files and SAFContainer and SAFDesigner controls
exist on every form.
Note: Code Inspector does not verify the presence of the following required files for
Customization Manager:
VBTApp.cls equals a VB Class Module. The components in this module are used
by Customization Manager to create controls at runtime and invoke the proper
customization Help files during Customization Mode.
Even if the project does not actually use a Tab control, a reference is created and
compiled into the application so that the Customization Manager Insert Object Wizard
can successfully add the Tab object.
Code Inspector verifies that all of the applications form files contain an instance of
both a VB.Frame control as well as a TabDlg.SSTab control. The following are the
specific tests performed.
Each occurrence of a form has the following entry in its .FRM form file:
Object = "{BDC217C8-ED16-11CD-956C-0000C04E4C0A}#1.1#0";
"TABCTL32.OCX"
Begin TabDlg.SSTab SAFNewTab
Enabled
Index
Left
Visible
End
= 0 'False
= 0
= -20000
= 0 'False
62
= 0 'False
= 0
= -20000
= 0 'False
End
[VBCodeInspector-ProcessOptions]
This section contains entries that allow you to define Update and Logging default
options for the VB Code Inspector.
allow_option_change allows you to determine whether the user interface will allow
the any changes to the default configuration.
logfile allows you to decide whether you would like a log file to be created.
logonly determines whether the VB Code Inspector will display messages to the
screen as problems are detected.
no_update determines whether updates to the VB code will be allowed during code
inspection.
append_to_existing_file determines whether one log file will be created for all
code inspections (named vbcodeinspector.log) or one file will be created for each
application (named <projectname>.log).
print_config_in_logfile determines whether the log file created will contain the
configuration settings being used at the time of the VB code inspection.
customization_check enables additional, optional checks specific to customization.
logo_check enables additional, optional checks for Microsoft Designed for
Windows Client logo requirements.
configuration_check enables additional, optional checks for control property
setting guidelines that may be set up by your development group.
63
[VBCodeInspector-WarningOptions]
This section contains entries that allow you to define additional, optional, code
inspection tests that may be performed. These tests are classified as warnings because
they are considered to be less critical issues. It is recommended that these warnings be
enabled at some point during code inspection so the messages may be logged for
further evaluation at some time.
fieldclass_min_max_check enables the warning check for SAF.SAFFloat controls
with a Fieldclass property set to 124, 125, or 126 that do not have their Min and Max
properties set to all 9s.
text_property_assignment_check enables the warning check for specific control
properties (Caption, Heading, and Text) being assigned to literal values.
mask_warning_check enables the warning check for SAF.SAFMaskedText Mask
property where the number of characters specified is fewer than the actual field size as
it is defined to the application.
controls_outside_frame_check enables the warning check for visible controls that
are outside the boundaries of a grid container.
tabindex_in_and_out_of_frame_check enables the warning check for controls
inside a container whose tabindex property values are less than the tabindex for the
container, or for controls outside the container that have tabindex property values that
are greater than the container, but less than the largest tabindex property value of all
controls inside the container.
sqlcursorex_use_check enables the warning check for the use of SQLCursor
instead of the preferred SQLCursorEX.
use_of_third_party_controls_check enables the warning check for the use of
third-party controls in the application that will not be available to the Template
function, and Application Server processing.
invalid_property_assignment_check enables the warning check for specific
control properties being assigned explicitly and not through the use of the SetProps
API.
blank_in_level_property_check enables the warning check for a blank in the level
property of a SAF control.
order_of_update_levels_check enables the warning check for non-detail levels
that are defined in the SAF.SAFUpdate control after detail levels have been defined.
use_of_a_range_of_controls_check enables the warning check for all Solomon
APIs that allow the use of a range of controls to see if the same control is identified as
the beginning and ending control. The warning will appear if the same control is NOT
the beginning and ending control. This is particularly useful when you change the tab
order of controls. If you have used control ranges, these commands may be affected by
changing tab order.
pv_or_dbnav_check enables the warning check for no PV or DBNav identified as
the last key field of any N(avigation) level.
64
[VBCodeInspector-RequiredReferences]
This section identifies the references that will be required for any VB Tools project.
The references required by Solomon are entered here for illustration only. They are
actually hard-coded into the VB Code Inspector, however additional required
references may be added here for specific development group needs.
For example, the SQAOTest.SQAObjectTestingControl is not required for all
applications; however, if your development group uses SQA for automated testing, you
may want to be sure that all applications contain this reference.
The format for this section is:
ref?=ControlName,ControlFile,SearchStr1,SearchStr2
?: Is an integer incremented by 1 each time.
ControlName: Progid listed in the registry for this reference.
ControlFile: Actual filename for the reference.
SearchStr1: Library name for the actual control (can be found in the Object Browser).
SearchStr2: - (optional) Alternate Library name.
[VBCodeInspector-RequiredComponents]
This section identifies the components required by any VB Tools project. The
components required by Solomon are entered here for illustration only. They are
actually hard-coded into the VB Code Inspector. However additional required
components may be added here for specific development group needs.
The format for this section is:
comp?=componentfilename
?: Is an integer incremented by 1 each time.
Componentfilename: Actual filename of the required component (path is not
specified).
65
[VBCodeInspector-RequiredControls]
This section is used to identify the controls required by any VB Tools project. The
controls required by Solomon are entered here for illustration, only. They are actually
hard-coded into the VB Code Inspector. However, additional required controls may be
added.
The format for this section is:
ctl?=ControlLibrary.Class,ControlName,Index,AllForms
?: Is an integer incremented by 1 each time.
ControlLibrary.Class: The Library and Class for the control. Use Object Browser to
determine this.
ControlName: The name assigned to the control when it is pasted on the form.
Index: The index value to be assigned to the control. (-1 is the value for no index).
AllForms: An indicator of whether the control should be on all forms, or just Form1.
If Allforms = -1 then the control must be on all forms. If Allforms = 0 then the control
should only be on Form1.
[VBCodeInspector-RequiredProperties:ControlName]
This section may be repeated for each controlname specified in the [VBCodeInspectorRequiredControls] section. It is used to validate/assign properties for the required
controls. If the Required control exists, then the properties for that control are validated
against the properties assigned here. If the Required control does not exist and you
decide to paste it on the form, this section will be used to assign the appropriate
properties to the control.
The format for this section is:
Prop?=propname,propvalue
?: Is an integer incremented by 1 each time.
propname: Name of the control property.
propvalue: Value of that property to be assigned/validated.
[VBCodeInspector-LogoControls]
This section identifies controls whose properties will need to be checked for the
Microsoft Designed for Windows Client logo checking. Solomon has provided the
correct Logo-checking configuration in this file. There should be no reason to change
the current configuration. To disable Logo checking, set logo_check=0 in the
[VBCodeInspector-ProcessOptions] section.
The format for this section is:
ctl?=ControlLibrary.Class
?: Is an integer incremented by 1 each time.
ControlLibrary.Class: ControlLibrary and Class value for the control to be checked.
This value may be found using the Visual Basic Object Browser.
66
[VBCodeInspector-LogoProperties:ControlLibrary.Class]
This section may be repeated for each ControlLibrary.class specified in the
[VBCodeInspector-LogoControls] section. Solomon has provided the correct Logochecking configuration in this file. There should be no reason to change the current
configuration. To disable Logo checking, set logo_check=0 in the [VBCodeInspectorProcessOptions] section.
The format for this section is the same as for the [VBCodeInspectorRequiredProperties:ControlName] section.
[VBCodeInspector-ConfigControls]
This identifies controls whose properties should be checked for property value
consistency.
The format for this section is the same as for the [VBCodeInspector-LogoControls]
section.
[VBCodeInspector-ConfigProperties:ControlLibrary.Class]
This section may be repeated for each ControlLibrary.class specified in the
[VBCodeInspector-ConfigControls] section. It is used to assign property values to
specific control types.
The format for this section is:
prop?=propname,propvalue,exception,inclusion
?: is an integer incremented by 1 each time.
Propname: Name of the property for that control.
Propvalue: Property value to be validated/assigned for that control.
Exception: A specific exception to the property rule. A controlname that is to be
excluded from this property assignment.
Inclusion: Specific controlname that is to be assigned this property value. No other
controlname of this same type will get this property assignment/validation.
67
68
Required Fields
A new feature in 6.0 is the ability for VBTools applications to have a notation for the
required fields on a screen. As the application loads, the kernel determines which fields
are required to be entered by the end user. The BlankErr property is checked. If the
field is required, then the fields border is shaded a user Defined color, which is set
in User Maintenance (95.260.00). Here are few rules of use:
Required fields that are disabled will not have the border colored until the control
becomes enabled.
Combo Boxes are never colored, as they already have a value set.
Check boxes are never colored, as they already have a value set.
Option buttons are never colored, assuming they have a value set.
69
Delta.mnu
Maintenance Screens
Delta.mnu
Delta.mnu is the traditional Solomon menu file. Changes in this file can cause the
menu shown in the Parent application to be altered. The order of modules shown in the
Module Navigation Pane is dictated by the order of modules in the Delta.mnu.
The list of executables contained in a module is dictated by Screen Category
Maintenance (98.310.00).
Applications listed in Delta.mnu that are not contained in a Screen Category will
appear on the menu under the heading of Misc.
ScreenCategory
ScreenMenu
Userrec
70
Maintenance Screens
Screen Category Maintenance (98.310.00): Use this screen to create categories for
your modules, or screens. Upon Upgrade, ALL records defined for the Group
EVERYONE will be removed and replaced with our settings. Other records
defined for other groups, or specific users will not be effected.
Modules Maintenance (98.320.00): Use this screen to add your modules to the list
of modules. Your entries will not be removed during a future database upgrade. It
is extremely important that the module name defined here is the same as it appears
in the DELTA.MNU file.
Screen Maintenance (98.330.00): Use this screen to add your applications to the
list of screens. Your entries will not be removed during a future database upgrade.
Reference
71
Reference
Controls
SAFDate Control
ToolBox Icon
Description
The SAFDate is a bound control which can display a date that is entered by the user or
programmatically assigned to the underlying date data field at run time. The display
format of the SAFDate control is determined by Windows Short International Date
format.
Remarks
The SAFDate control supports the following hotkeys for editing a date field:
Key
F3
Purpose
F7
Displays a pop-up calendar from which the user may select a date. A double
right click within the control will also display the calendar.
Properties
Alignment
Font
**Max
TabStop
BackColor
ForeColor
**Min
Tag
**BlankErr
Heading
MouseIcon (D)
ToolTipText
Custom
Height
MousePointer (D)
Top
Default
HelpContextID
Name (D)
Trigger (D)
*DragIcon
Index (D)
NoteButton
**Visible
*DragMode
InGrid (D)
Spin
WhatsThisHelpID
**Enabled
Left
SpinIncrement
Width
FieldName (D)
Level (D)
TabIndex (D)
** Property values can be narrowed at runtime but not expanded, depending on the level at
which the changes are being made (All User, One User, etc.). See the Security section of
the Customization Manager documentation.
(D) The property can be modified only at design time but not at runtime.
72
Events
Chk
*DragDrop
GotFocus
MouseDown
Default
*DragOver
LostFocus
MouseMove
*Validate
*
Methods
AboutBox
*Move
ShowWhatsThis
*Drag
*SetFocus
*ZOrder
See Also
DispField Statements, SetAddr Statement, SetDefaults Statement, SetProps
Statement
Reference
73
SAFFloat Control
ToolBox Icon
Description
The SAFFloat is a bound control which can display a floating point value that is
entered by the user or programmatically assigned to the underlying double precision
data field at run time.
Remarks
The SAFFloat control supports the following hotkeys for editing a numeric data
field:
Key
Purpose
F2
Properties
Alignment
FieldClass (D)
Left
TabIndex (D)
BackColor
FieldName (D)
Level (D)
TabStop
**BlankErr
Font
**Max
Tag
Custom
ForeColor
**Min
ToolTipText
DecimalPlaces (D)
Heading
MouseIcon (D)
Top
Default
Height
MousePointer (D)
Trigger (D)
*DragIcon
HelpContextID
Name (D)
**Visible
*DragMode
Index (D)
NoteButton
WhatsThisHelp
**Enabled
InGrid (D)
Separator
Width
** Property values can be narrowed at runtime but not expanded, depending on the level at
which the changes are being made (All User, One User, etc.). See the Security section of
the Customization Manager documentation.
(D) The property can be modified only at design time but not at runtime.
The valid FieldClass property values are embedded inside of the control and are
viewable via a ComboBox in the VB Property Window.
Events
Chk
*DragOver
MouseDown
Default
GotFocus
MouseMove
*DragDrop
LostFocus
MouseUp
74
Methods
AboutBox
*Move
ShowWhatsThis
*Drag
*SetFocus
*ZOrder
See Also
ApplSetFocus Statement, DispField Statements, SetAddr Statement, SetDefaults
Statement, SetProps Statement
Reference
75
SAFInteger Control
ToolBox Icon
Description
The SAFInteger is a bound control which can display an integer value that is entered
by the user or programmatically assigned to the underlying integer data field at run
time.
Remarks
The SAFInteger control supports the following hotkeys for editing an integer data
field:
Key
Purpose
F2
Properties
Alignment
Font
BackColor
ForeColor
**Min
Tag
**BlankErr
Heading
MouseIcon (D)
ToolTipText
Custom
Height
MousePointer(D)
Top
Default
HelpContextID
Name (D)
Trigger (D)
*DragIcon
Index (D)
NoteButton
**Visible
*DragMode
InGrid (D)
Spin
WhatsThisHelpID
**Enabled
Left
SpinIncrement
Width
FieldName (D)
Level (D)
TabIndex (D)
**Max
TabStop
** Property values can be narrowed at runtime but not expanded, depending on the level at
which the changes are being made (All User, One User, etc.). See the Security section of
the Customization Manager documentation.
(D) The property can be modified only at design time but not at runtime.
Events
*DragOver
MouseDown
Default
GotFocus
MouseMove
*DragDrop
LostFocus
MouseUp
Chk
76
Methods
AboutBox
*Move
ShowWhatsThis
*Drag
*SetFocus
*ZOrder
See Also
DispField Statements, SetAddr Statement, SetDefaults Statement, SetProps
Statement
Reference
77
SAFMaskedText Control
ToolBox Icon
Description
The SAFMaskedText is a bound control which can display text information that is
entered by the user or programmatically assigned to the underlying string data field at
run time.
Remarks
The SAFMaskedText control supports the following hotkeys for editing a string
data field:
Key
Purpose
F2
F3
Properties
Alignment
FieldName (D)
Level (D)
Tag
BackColor
Font
**Mask
ToolTipText
**BlankErr
ForeColor
MouseIcon (D)
Top
DBNav (D)
Heading
MousePointer (D)
Trigger (D)
Default
Height
Name (D)
**Visible
*DragIcon
HelpContextID
NoteButton
WhatsThisHelp
Width
*DragMode
Index (D)
PV (D)
**Enabled
InGrid (D)
TabIndex (D)
FieldClass (D)
Left
TabStop
** Property values can be narrowed at runtime but not expanded, depending on the level at
which the changes are being made (All User, One User, etc.). See the Security section of
the Customization Manager documentation.
(D) The property can be modified only at design time but not at runtime.
The valid FieldClass property values are embedded inside of the control and are
viewable via a ComboBox in the VB Property Window.
78
Events
Chk
*DragOver
MouseDown
Default
GotFocus
MouseMove
*DragDrop
LostFocus
MouseUp
Methods
AboutBox
*Move
ShowWhatsThis
*Drag
*SetFocus
*ZOrder
See Also
DBNavFetch Functions, DispField Statements, PVChkFetch Functions, SetAddr
Statement, SetDefaults Statement, SetProps Statement
Reference
79
SAFGrid Control
ToolBox Icon
Description
The SAFGrid is a bound control that can simultaneously display many records of
information. Spreadsheets are commonly referred to as grids.
Remarks
The SAFGrid control is used to implement Detail levels.
The font of the grid cell(s) can be modified at runtime by modifying the Font property
of the cell(s) corresponding form-view control.
The foreground color of the grid cell(s) can be modified at runtime by modifying the
ForeColor property of the cell(s) corresponding form-view control.
Grid-view help is driven by properties on the form-view controls. If the current
columns form-view partner has a help context, that value will be used. Otherwise, the
help context of the form-view container (e.g., the frame) will be used.
The background color of the grid cell(s) can be modified at runtime by modifying the
BackColor property of the cell(s) corresponding form-view control.
To vary the BackColor on a row-by-row basis, use a SetProp() call on the form-view
control. The SetProp() call should be made from within the LineGotFocus event of
the SAFGrid.
To modify the BackColor of an entire column, use a MSetProp() call on the form-view
control. Note that in the MSetProp() scenario, this call must be made before the
SAFGrid receives focus (such as at screen load, or in a master key Chk event of a
header level). Do not call MSetProp() from within SAFGrid events such as
LineGotFocus().
Grid-view tooltips are driven by the ToolTipText property on the form-view controls.
If the current columns form-view partner has a value for the ToolTipText property,
that value will be used.
The following steps outline the basic requirements to implement a single level detail
screen.
Database
1.
Create one or more database tables to hold the detail information from the grid.
2.
Create a stored procedure that will be used to retrieve the database information.
80
Set the Levels property of the SAFUpdate control. Add an alias;D or alias;DA to
the character string that is used to define the Levels property.
2.
3.
Paste one or more Solomon bound controls on top of this panel. These controls
should be pasted with a Level Number corresponding to the position of the new
level defined in step 1.
4.
5.
Set the DBNav property of the SAFGrid control to the name of a SQL stored
procedure created in step 2 of the Database requirements.
6.
Set the ColsFrozen property of the SAFGrid control to 0 to allow all columns of
the SAFGrid to scroll horizontally, or to 1 or higher to keep the left-most
column(s) from scrolling horizontally.
7.
If the detail records must appear in alphabetical order then the fields
corresponding to the Order By clause of the DBNav SQL statement should be
marked as key fields.
Code
1.
Add code to the Form1_Load event that the includes the SetAddr(), SqlCursor(),
and DetailSetup() calls for the new level.
2.
Properties
BackColor (R)
*Enabled
Left (D)
ColsFrozen (R)
Font (R)
Name (D)
*ToolTipText
Custom
ForeColor (R)
NoteButton
Top (D)
DBNav (D)
Height (D)
NoteColumn
Visible (R)
*DragIcon
*HelpContextID
TabIndex (D)
*WhatsThisHelp
*DragMode
*Index
TabStop
Width (D)
Tag
** Property values can be narrowed at runtime but not expanded, depending on the level at
which the changes are being made (All User, One User, etc.). See the Security section of
the Customization Manager documentation.
(D) The property can be modified only at design time but not at runtime.
(R) Following the property indicates that the property can be modified only at runtime but not at
design time.
Reference
Events
*DragDrop
LineChk
*DragOver
LineGotFocus
GotFocus
LostFocus
Methods
AboutBox
*Move
ShowWhatsThis
*Drag
*SetFocus
*ZOrder
See Also
DetailLoad Statement, DetailSave Statement, DetailSetup Functions, Font
Property, MDisplay Statement, MGetDelHandle Function, MSet Statement,
MSetProp Statement, SAFUpdate Control
81
82
SAFCheck Control
ToolBox Icon
Description
The SAFCheck is a bound control that displays an X when selected. The X disappears
when the check box is cleared by clicking it again. Use this control to give the user a
True/False or Yes/No option.
Remarks
The SAFCheck control functions similar to SAFOption buttons with one important
exception. In particular, any number of check boxes on a form can be selected at the
same time whereas only one SAFOption button can be selected within any particular
group.
To display a string literal next to the SAFCheck, set the Caption property. Use the
TrueText property to determine the data value that will be stored in the database when
the box is checked. The FalseText property determines the data value that will be
stored in the database when the box is unchecked.
Properties
Alignment
FalseText (D)
Left
Top
BackColor
FieldName (D)
Level (D)
Trigger (D)
**BlankErr
Font
MouseIcon (D)
TrueText (D)
Caption
ForeColor
MousePointer (D)
**Visible
Custom
Heading
Name (D)
WhatsThisHelp
Width
Default
Height
TabIndex (D)
*DragIcon
HelpContextID
TabStop
*DragMode
Index (D)
Tag
**Enabled
InGrid (D)
ToolTipText
** Property values can be narrowed at runtime but not expanded, depending on the level at
which the changes are being made (All User, One User, etc.). See the Security section of
the Customization Manager documentation.
(D) The property can be modified only at design time but not at runtime.
Reference
Events
Chk
*DragOver
MouseDown
Default
GotFocus
MouseMove
*DragDrop
LostFocus
MouseUp
Methods
AboutBox
*Move
ShowWhatsThis
*Drag
*SetFocus
*ZOrder
See Also
DispField Statements, SetAddr Statement, SetDefaults Statement, SetProps
Statement
83
84
SAFCombo Control
ToolBox Icon
Description
The SAFCombo is a bound control that combines the features of a text box and a list
box. Use this control to allow the user to select an item from a pre-defined list of valid
values.
Properties
BackColor
Font
Level (D)
Tag
**BlankErr
ForeColor
List (D)
ToolTipText
Custom
Heading
MouseIcon (D)
Top
Default
Height
MousePointer (D)
Trigger (D)
*DragIcon
HelpContextID
Name (D)
**Visible
*DragMode
Index (D)
NoteButton
WhatsThisHelp
**Enabled
InGrid (D)
TabIndex (D)
Width
FieldName (D)
Left
TabStop
** Property values can be narrowed at runtime but not expanded, depending on the level at
which the changes are being made (All User, One User, etc.). See the Security section of
the Customization Manager documentation.
(D) The property can be modified only at design time but not at runtime.
Events
Chk
*DragDrop
GotFocus
Default
*DragOver
LostFocus
Methods
AboutBox
*Move
ShowWhatsThis
*Drag
*SetFocus
*ZOrder
See Also
DispField Statements, SetAddr Statement, SetDefaults Statement
Reference
85
SAFOption Control
ToolBox Icon
Description
The SAFOption button is a bound control that displays an option that can be turned on
or off.
Remarks
SAFOption buttons are used as part of an option group to display multiple choices
from which the user can select only one. SAFOption buttons can be grouped by
drawing them inside a VB Frame. To group option buttons in a frame, draw the frame
first, then draw the option buttons inside. All option buttons within a container, such as
a frame, are treated as a group.
While option buttons and check boxes may appear to function similarly, there is one
important difference. When a user selects an option button, all other option buttons in
the same group are then turned off. In contrast, multiple check boxes can be selected.
If an option button group appears within a grid, the grid uses the Heading property of
the first option button as the column header.
To display a string literal next to the SAFOption button, set the Caption property. Use
the TrueText property to determine the data value that will be stored in the database
when the option button is selected.
The following property values are always derived from the first option button in the
group, since by definition only one option button can be selected within any particular
group: BlankErr, Default, FieldClass, FieldName, Heading, Level and Trigger.
Properties
Alignment
**Enabled
InGrid (D)
Tag
BackColor
**BlankErr
Caption
Custom
Default
*DragIcon
*DragMode
FieldName (D)
Font
ForeColor
Heading
Height
HelpContextID
Index (D)
Left
Level (D)
MouseIcon (D)
MousePointer (D)
Name (D)
TabIndex (D)
TabStop
ToolTipText
Top
Trigger (D)
TrueText (D)
**Visible
WhatsThisHelp
Width
** Property values can be narrowed at runtime but not expanded, depending on the level at
which the changes are being made (All User, One User, etc.). See the Security section of
the Customization Manager documentation.
(D) The property can be modified only at design time but not at runtime.
86
Events
Chk
*DragOver
MouseDown
Default
GotFocus
MouseMove
*DragDrop
LostFocus
MouseUp
Methods
AboutBox
*Move
ShowWhatsThis
*Drag
*SetFocus
*ZOrder
See Also
DispField Statements, SetAddr Statement, SetDefaults Statement, SetProps
Statement
Reference
87
SAFUpdate Control
ToolBox Icon
Description
The SAFUpdate control is used to define logical groups of information on the screen
via its Levels property as well as expose key database and/or navigational events to the
application such as NewLevel, Delete and Finish.
Remarks
All applications developed must have an SAFUpdate control on Form1.
Properties
Customizable (D)
Left
Name (D)
Index (D)
Levels (D)
Tag
Top
(D) The property can be modified only at design time but not at runtime.
Events
Cancel
Finish
Delete
NewLevel
Update
Methods
AboutBox
See Also
Level Property, SqlCursor Statement, SetAddr Statement
88
Properties
Alignment Property
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFCheck, SAFOption
Description
Returns or sets a value that determines the alignment of a CheckBox or OptionButton
control, text in a control.
Remarks
The object is an object expression that evaluates to an object in the Applies To list. The
number is an integer that specifies the type of alignment.
For the SAFCheck and SAFOption controls, an Alignment number 0 indicates that
the text is left aligned and the control is right aligned. An alignment value of 1
indicates that the text is right aligned and the control is left aligned. You can display
text to the right or left of SAFOption and SAFCheck controls. By default, text is left
aligned.
For the SAFMaskedText control, the default value of 0 indicates the text is left
aligned; a value of 1 indicates the text is right aligned; a value of 2 indicates the text is
centered.
To modify the value of the Alignment property at runtime, the SetProps statement
should be used rather than modifying the property directly in VB code. Usage of
SetProps allows the system to track changes to property values so as to avoid conflicts
with customizations.
See Also
SetProps
Reference
89
BackColor Property
Applies To
SAFDate, SAFFloat, SAFInteger, SAFCheck, SAFCombo, SAFGrid,
SAFMaskedText, SAFOption
Description
Specifies the background color of an object.
Remarks
The BackColor of grid cell(s) can be modified at runtime by modifying the BackColor
property of the particular cells corresponding form-view control:
See Also
LineGotFocus Event, MsetProp Statement, SetProps Statement
90
BlankErr Property
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFCheck, SAFCombo,
SAFOption
Description
Determines whether or not a valid value must be entered or defaulted for the field.
Remarks
A setting of True indicates that the field requires a value. A setting of False indicates
the field is optional. Disabled and/or invisible fields should not be required unless they
are automatically defaulted with a valid value. If a control is marked as required by the
application then it cannot be marked as optional using the Customization Manager.
However if a control is marked as optional by the application then it can be marked as
required by the Customization Manager.
To modify the value of the BlankErr property at runtime, the SetProps statement
should be used rather than modifying the property directly in VB code. Usage of
SetProps allows the system to track changes to property values so as to avoid conflicts
with customizations.
See Also
Enabled Property, MSetProp Statement, SetProps Statement, Visible Property
Reference
91
Caption Property
Applies To
SAFCheck, SAFOption
Description
Determines the text displayed next to the control.
Remarks
To modify the value of the Caption property at runtime, the SetProps statement
should be used rather than modifying the property directly in VB code. Usage of
SetProps allows the system to track changes to property values so as to avoid conflicts
with customizations.
See Also
SetProps Statement
92
ColsFrozen Property
Applies To
SAFGrid Control
Description
Sets the number of left-most columns in an SAFGrid that remain visible when the
SAFGrid scrolls horizontally.
Remarks
The value of ColsFrozen defaults to 0. The maximum number of columns that can be
frozen is the total number of columns in the SAFgrid. If the value specified for
ColsFrozen is greater than the number of columns in the SAFGrid, then all columns
will be frozen. ColsFrozen does not affect vertical scrolling.
ColsFrozen refers to the ordinal column position from left to right. For example,
assume an SAFGrid contains columns A, B, C, etc., and column Z is inserted before
column A at runtime. If ColsFrozen is set to 1, column Z is frozen.
The value of ColsFrozen is modifiable at runtime.
Reference
Description
An SAF Control may have one or more properties that have an associated properties
page. For example, it is common for an SAF Control to have both a BackColor
property and a FieldName property assigned. Both of these properties have an
associated property page. The Custom Property Page presents all relevant property
pages for the specified control in a single dialog box.
93
94
Customizable Property
Applies To
SAFUpdate
Description
Determines whether an application is customizable.
Remarks
This property allows an application to identify itself as non-customizable. It is a
Boolean property. The default value is True, which means that the application is
customizable. False indicates that the application cannot be customized.
Reference
95
DBNav Property
Applies To
SAFMaskedText, SAFGrid
Description
Used to facilitate navigation through all database records in the result set of a SQL
statement.
Remarks
When the DBNav property of an SAFMaskedText control is used, it is conceptually
equivalent to the PV property except that the PV window is not applicable. Some data
entry screens contain multiple key fields. If the valid values for the last key field (e.g.,
the control that navigation is performed on) are not restricted to values from some
referential table, then the DBNav property should be used instead of the PV property.
In this case, the application needs to explicitly fetch the record from within its Chk
event using one of the DBNavFetch functions.
For example, the master table for the Payroll Employee W2 History screen is the
W2Federal table. The unique index for that table contains two fields, EmpId and
CalYr, representing the Employee ID and Calendar Year respectively. Consequently,
the application itself also has two key fields corresponding to the unique index. The
first key field is EmpID and a PV property referencing the Employee table is
implemented for that control. However the CalYr field is the last master key and
therefore the W2Federal record is actually fetched within its Chk event. Since Payroll
does not have a referential table containing all possible calendar year values, the
Possible Values window is not applicable. Therefore that particular control utilizes a
combination of a DBNav property and a corresponding DBNavFetch call within its
Chk event.
The only other usage of the DBNav property is for the SAFGrid control. In this case,
it is used to load the grid with all of the records contained within the result set of the
SQL statement or stored procedure referenced in the DBNav property.
Spreadsheets are always associated with one of two different types of detail levels:
Detail or Detail (Application Loaded). The actual level type in use for any particular
grid is specified in the Levels property of the SAFUpdate control. For standard Detail
levels, an SQL statement or stored procedure must be entered in the DBNav property
of the corresponding SAFGrid control. However for Application Loaded Detail levels,
a DBNav property value is optional depending on whether or not the DetailLoad
statement will be used to load the corresponding SAFGrid. If DetailLoad is utilized
then a SQL statement or stored procedure must be entered in the DBNav property of
the corresponding SAFGrid control. However, if the application loads the SpreadSheet
via the use of MInsert calls within a SqlFetch ... SFetch type of loop then a DBNav
property value is not required. In this latter case, however, the application MUST
assume full responsibility for the update since it is taking complete control of the load
operation.
96
Description
SQL Proc/Text
Constant
Wildcard
Struct.FieldName
Used in conjunction with the Parm tabs to pass the value of other
data items as a runtime parameters to the SQL statement or stored
procedure. The Struct.FieldName value will normally be in the
bTableName.FieldName format. The portion of the entry that
identifies the table name MUST correspond precisely to the table
name string passed in a corresponding call to the SetAddr
statement. For example, assume the value of TableA.FieldA
should be passed as a runtime parameter to the stored procedure.
In this case, the Struct.FieldName would be bTableA.FieldA.
Declare Type
Length
Parm Tabs
Example 1
Select * from TableA
where TableA.StringField LIKE @parm1
Order By StringField
Reference
97
Example 2
Select * from TableA
where TableA.StringFieldA
= @parm1
Example 3
Select * from TableA
where TableA.StringFieldA
= @parm1
The first two examples use the LIKE statement for the last string field. Because the
LIKE keyword does not apply to integer fields, the BETWEEN keyword is used for
integers in the third example. When the system handles wildcard values for a single
integer parameter it will automatically pass two parameters, the first having a value
corresponding to INTMIN and the last having a value corresponding to INTMAX.
When implementing a DBNav property on an SAFMaskedText, the value of the
underlying control is always passed to the SQL statement or stored procedure as the
LAST parameter. Consequently the last parameter does not need to be manually
defined using the Parm buttons. For example, if the stored procedure has only one
parameter then no parameters need to be manually defined within the DBNav property.
This is due to the fact that the value of the underlying control will automatically be
passed as the last parameter - which happens to be the only parameter in this particular
case.
When implementing a DBNav property on an SAFGrid control, all parameters must
be defined using the Parm buttons. The only exception is for wildcard integers in
which case one integer parameter is defined but is marked as a Wildcard.
The restriction clause of the SQL statement or stored procedure MUST be capable of
retrieving one unique record. For example, assume that the SAFGrid is loaded with
ten existing records. Furthermore, assume that the user subsequently modifies only the
third record. In this case, the DBNav SQL statement or stored procedure MUST be
capable of targeting only that third record.
See Also
Chk Event, DBNavFetch Functions, DetailLoad Statement, DetailSave Statement,
FieldName Property, PV Property, SetAddr Statement
98
DecimalPlaces Property
Applies To
SAFFloat
Description
Determines the number of digits displayed to the right of the decimal separator.
Remarks
Developers should use caution when setting the DecimalPlaces property. In particular,
when writing applications which integrate with Solomon applications, the data will
ultimately be processed by Solomon. Consequently, the data will be rounded by
Solomon. The exact precision will vary depending on the type of number involved.
The point however, is merely to remind the developer that extended precision will only
have worth if all subsequent uses of such numbers are rounded correspondingly.
Neither the application itself nor custom BSL code can change this property at runtime.
However, the kernel changes the DecimalPlaces property in order to facilitate Flexible
Decimal Precision feature, such as Float controls associated with a FieldClass.
The DecimalPlaces property can be modified only at design time; it cannot be
modified at runtime.
See Also
Max Property, Min Property
Reference
99
Default Property
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFCheck, SAFCombo,
SAFOption
Description
Determines the default value for the underlying data field.
Remarks
The default data value for any particular data entry control can be specified via either
the Default property or the Default event.
The Default property can be used when the default value is not contingent upon any
the value of any other data item. However, if the methodology for determining a
default value varies depending particular situations, then code should be written for the
Default event. If a Default property is defined then the Default event will not be used.
The Default property value for an SAFOption button group is always derived from the
first option button in the group, since by definition only one option button can be
selected within any particular group.
The Default property dialog contains the following fields:
Field
Description
Constant
Used to specify a constant data value for the underlying control. For
example, if SAFCheck should always default to True, then a value of
1 would be entered (assuming that is the value of its TrueText
property)
Previous Value
Struct.FieldName
Used in cases where the value of the field should always default to
the value of some other data item. This value will normally be in the
bTableName.FieldName format. The portion of the entry that
identifies the table name MUST correspond precisely to the table
name string passed in a corresponding call to the SetAddr statement.
For example, assume the value of TableB.FieldB should default to
the value of TableA.FieldA. In this case, the Default property for the
TableB.FieldB control should have a Struct.FieldName of
bTableA.FieldA.
100
Field
Description
Declare Type
Length
See Also
Default Event, FieldName Property, Level_SetDefaults Statement, SetDefaults
Statement, Trigger Property
DragIcon Property
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFGrid, SAFCheck,
SAFCombo, SAFOption
Description
Reserved for Microsoft Business Solutions and should not be changed at design or
runtime.
DragMode Property
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFGrid, SAFCombo,
SAFOption
Description
Reserved for Microsoft Business Solutions and should not be changed at design or
runtime.
Reference
101
Enabled Property
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFCheck, SAFCombo,
SAFOption
Description
Determines whether or not the user can modify the contents of the control.
Remarks
A value of True indicates that the control is enabled whereas a value of False causes
the control to be disabled. Required fields should not be disabled unless they are
automatically defaulted with a valid value.
To modify the value of the Enabled property at runtime, the SetProps statement
should be used rather than modifying the property directly in VB code. Usage of
SetProps allows the system to track changes to property values so as to avoid conflicts
with customizations and / or other APIs such as the DisplayMode statement.
If a control is disabled by the application then it cannot be enabled using the
Customization Manager. However if a control is enabled by the application then it can
be disabled by the Customization Manager. The value of the Enabled property can be
narrowed at runtime but not expanded, depending on the level at which the changes are
being made (All User, One User, etc.). See the Security section of the Customization
Manager documentation. The Enabled property should not be used on the SAFGrid
control.
See Also
BlankErr Property, DisplayMode Statement, SetProps Statement, Visible
Property
FalseText Property
Applies To
SAFCheck
Description
Determines the value of the underlying data field whenever the control is not checked.
Remarks
Normally the FalseText value for integer true/false type of fields is 0. This allows the
value to more easily be tested for a false value within SQL. It also corresponds to the
value of the LFALSE symbolic constant declared in Applic.DH. The FalseText
property can be set only at design time.
See Also
TrueText Property
102
FieldClass Property
Applies To
SAFFloat, SAFMaskedText
Description
Associates a control with a particular class of data items having global display and/or
operational characteristics.
Remarks
Within Solomon, some classes of fields have unique characteristics across the entire
product line.
For example, Subaccounts can have a user-defined mask based on the segmentation
defined in Flexkey Definition (21.320) in Shared Information. All controls whose
underlying data field is a Subaccount have a FieldClass property value identifying
them as such (e.g., as Subaccount fields). When the screen containing the Subaccount
field is actually displayed, the system will have automatically applied a custom mask
corresponding to the globally defined Subaccount segmentation rules.
The valid FieldClass values are embedded inside of the control and are viewable by the
developer via a ComboBox in the VB Property Window. The user cannot change the
FieldClass property at runtime, but can only change it at design-time via the Property
Window, which will explicitly present a valid list of possible values.
The following table contains all of the valid values for the FieldClass property. Each
fieldclass is either of two types: Flex Key and Non-Flex Key.
Flex Key Type Fieldclasses
Customer ID (3)
Country/Region (103)
Vendor ID (4)
Employee ID (109)
Reference
103
Solomon Standard
Solomon
The number of segments can be up to 8; the total length of all segments can be up
to 24 characters
Application Requirements:
104
Solomon Standard
Solomon
The number of segments can be up to 4; the total length of all segments can be up
to 30 characters
Application Requirements:
Customer ID (3)
Developer Benefits:
Solomon Standard
Solomon
The number of segments can be up to 4; the total length of all segments can be up
to 15 characters
Application Requirements:
Reference
105
Vendor ID (4)
Developer Benefits:
Solomon Standard
Solomon
The number of segments and combined length are determined by the information
entered in Shared Information on Flex Definition (21.320.00)
The number of segments can be up to 4; the total length of all segments can be up
to 15 characters
Application Requirements:
Employee ID (109)
Developer Benefits:
Solomon Standard
Solomon
The number of segments can be up to 4; the total length of all segments can be up
to 10 characters
Application Requirements:
106
When error-checking occurs on this field, the kernel will display System Message
786 if the account selected by the user is not an active account
Application Requirements:
The control must have the PVNav property set, and the stored procedure specified
there MUST return a structure exactly like the Account table as it is defined in an
application database
Application Requirements:
Country/Region (103)
Developer Benefits:
None
Application Requirements:
Reference
107
Allows entry of a persons name with the @ symbol placed in front of the portion
of the name on which to sort; for example, John@Doe entered in the control is
stored in the database as Doe~John to allow sorting by Last Name
Application Requirements:
Deduction ID (106)
Developer Benefits:
None
Application Requirements:
Depreciation ID (107)
Developer Benefits:
None
Application Requirements:
None
Application Requirements:
Application Requirements:
108
Project ID (111)
Developer Benefits:
Application Requirements:
Kit ID (112)
Developer Benefits:
None
Application Requirements:
None
Application Requirements:
The Period is checked against the GL and message 6071 is issued if the period
entered is less than the XXXXX entered in GL Setup
Message 23 is displayed if the period entered is not the same as the modules
current period
Message 22 is displayed if the period is invalid (less than 1, or greater than the
defined number of fiscal periods as defined in GL Setup)
Application Requirements:
Reference
Solomon Standard
Solomon
Application Requirements:
None
Application Requirements:
Salesperson ID (117)
Developer Benefits:
None
Application Requirements:
Site ID (118)
Developer Benefits:
None
Application Requirements:
109
110
State( 119)
Developer Benefits:
None
Application Requirements:
None
Application Requirements:
Terms ID (121)
Developer Benefits:
None
Application Requirements:
None
Application Requirements:
Flexible decimal precision, based on number of decimals for the base currency or
the transaction currency
Application Requirements:
Application Requirements:
Reference
111
Flexible decimal precision, based on the following setting in the Solomon.ini file
(0-99):
[Miscellaneous]
UnitPriceOverride=2
Application Requirements:
112
FieldName Property
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFCheck, SAFCombo,
SAFOption
Description
Facilitates proper runtime binding between the control and its underlying VB data
variable by operating in conjunction with the SetAddr statement.
Remarks
The data for each individual data entry control is actually stored in an underlying VB
variable. At runtime the control and its associated VB storage variable are bound
together using a combination of the FieldName property of the control and a
corresponding call to the SetAddr statement from within Form1_Load.
The FieldName property contains a Struct.FieldName value along with other more
detailed information such as Field Offset Value, Declare Type and Length. At a
minimum, a value must be entered into the Struct.FieldName field. This value will
normally be in the bTableName.FieldName format. The portion of the entry that
identifies the table name MUST correspond precisely to the table name string literal
which is passed in a corresponding call to the SetAddr statement. It is not, however,
required to correspond to the name of an actual table within the database.
The Field Offset Value, Declare Type and Length fields are optional depending on
whether or not the table name referenced by the Struct.FieldName is actually the name
of a table in the database. If the Struct.FieldName does reference a database table then
SWIM can access detailed information relating to each individual field contained
therein using the SQL data dictionary. If the referenced table name does not
correspond to the name of a table in the database then values MUST be entered in the
Field Offset Value, Declare Type and Length fields.
The FieldName property can be modified at design time only; it cannot be modified at
runtime.
The following table contains the Declare Type and Length of several standard
datatypes.
SQL Datatype
VB Datatype
Declare Type
Length
Character
String
Length of String
Integer(2)
Integer
Float
Double
Date
SDate
Logical
Integer
See Also
SetAddr Statement
Reference
113
Font Property
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFGrid, SAFCheck,
SAFCombo, SAFOption
Description
Used to identify a specific Font for an object.
Remarks
The Font of grid cell(s) can be modified at runtime by modifying the Font property of
the particular cells corresponding form-view control:
To vary the Font on a row-by-row basis, make a SetProps() call on the form-view
control from within the LineGotFocus event of the SAFGrid.
To modify the Font of an entire column, make an MSetProp() call on the formview control. In the MSetProp() scenario, this call must be made before the
SAFGrid receives focus (such as at screen load, or in a master key Chk event of a
header level). Do not call MSetProp() from within SAFGrid events such as
LineGotFocus().
See Also
Chk Event, LineGotFocus Event, MSetProp Statement, SetProps Statement
ForeColor Property
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFCheck, SAFCombo,
SAFOption, SAFGrid
Description
Specifies the foreground color used to display data in an object.
Remarks
The Foreground Color of grid cell(s) can be modified at runtime by modifying the
ForeColor property of the particular cells corresponding form-view control:
See Also
LineGotFocus Event, MsetProp Statement, SetProps Statement
114
Heading Property
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFCheck, SAFCombo,
SAFOption
Description
Contains the caption for the corresponding grid column for controls actually associated
with a SAFGrid.
Remarks
Column headings containing more than one line can be implemented by separating the
text for each line with a comma such as Line One, Line Two.
To modify the value of the Heading property at runtime, the SetProps statement
should be used rather than modifying the property directly in VB code. Usage of
SetProps allows the system to track changes to property values so as to avoid conflicts
with customizations.
If an option button group appears within a grid, the grid uses the Heading property of
the first option button as the column header.
See Also
MSetProp Statement, SetProps Statement
Reference
115
Height Property
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFCheck, SAFCombo,
SAFOption, SAFGrid
Description
Determines the dimensions of the control.
Remarks
To avoid potential conflicts with customizations applied at runtime using the
Customization Manager, do not modify the dimensions of a control at runtime.
The Height property of the SAFGrid control can be modified only at design time.
This property exists at both design-time and runtime. When you put an SAFGrid on a
form at design-time, it will have values for the sizing properties (Left, Top, Height,
Width). You can modify these values to optimize the size of the grid for design-time
viewing. You can size the grid quite small and put it in the lower-right corner of the
frame in which the SAFGrid resides to make it easier to see and/or manipulate all of
the form-view controls to which the SAFGrid will be bound.
At runtime however, do not modify this property since the kernel will seek to take total
responsibility over the sizing of the SAFGrid. For example, the kernel will attempt to
make the SAFGrid match the size of the underlying frame. The kernel will also resize
the SAFGrid when the user resizes the form.
See Also
Left Property, Top Property, Width Property
116
HelpContextID Property
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFCheck, SAFCombo,
SAFOption, SAFUpdate
Description
Specifies an associated context number for an object.
Remarks
The HelpContextID property can be used to provide context-sensitive Help for an
application.
You must assign the same context number to both object and to the associated Help
topic when you compile your Help file. When a user presses the F1 key, Visual Basic
automatically calls Help and searches for the topic identified by the HelpContextID
for the object that has the focus. If HelpContextID is set to 0, then Visual Basic looks
in the HelpContextID of the objects container, and then that objects container, and
so on. If a nonzero current context number cant be found, the F1 key is ignored.
Do not use the HelpContextID property with the SAFGrid control. Grid-view help is
driven by properties on the form-view controls. If the current columns form-view
control has a help context, that value will be used. Otherwise, the help context of the
form-view container (e.g., the frame) will be used.
See Also
WhatsThisHelpID Property
Reference
117
Index Property
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFCheck, SAFCombo,
SAFOption, SAFUpdate
Description
Value used to uniquely identify the control within a control array.
Remarks
Do not use this property with SAFGrid (that is, do not put a grid into a control array).
When a control array is implemented, the name of each individual control within the
array has the same control Name. In this case, each control is differentiated from all
other controls in the same array by the value of its Index property.
The Customization Manager requires that all control names within a given application
be unique. Since by definition a control array contains more than one control with the
same Name, the Customization Manager uses the Index property to track
customizations for individual controls within the array.
Furthermore, controls should not be removed from the control array after release of the
application since the Customization Manager will not be able to apply customizations
referencing the old control index(s).
This property can be modified at design time only; it cannot be modified at runtime.
See Also
Name Property
118
InGrid Property
Applies To
SAFDate, SAFFloat, SAFInteger, SAFCheck, SAFCombo, SAFMaskedText,
SAFOption
Description
Determines whether or not the control is visible in grid view.
Remarks
A value of True indicates that the control is visible in grid view as a column. Otherwise
it is not visible as a column.
This property should be set at the time of design, or modified through the
Customization Manager. The SetProps statement can be used to modify it at the run
time, but it will be meaningless if used after the grid is already configured. This
property can also be changed using the Customization Manager.
See Also
SetProps statement, Visible property
Reference
119
Left Property
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFCheck, SAFCombo,
SAFOption, SAFGrid, SAFUpdate
Description
Determines the distance between the left edge of a control and the left edge of its
container object.
Remarks
To avoid potential conflicts with customizations applied at runtime using the
Customization Manager, do not modify the position of a control at runtime. The Left
property of the SAFGrid control can be modified only at design time.
This property exists at both design-time as well as runtime. When you put an SAFGrid
on a form at design-time, it will have values for the sizing properties (Left, Top,
Height, Width). You can modify these values to optimize the size of the grid for
design-time viewing. You can size the grid quite small and put it in the lower-right
corner of the frame in which the SAFGrid resides to make it easier to see and/or
manipulate all of the form-view controls to which the SAFGrid will be bound.
At runtime however, do not modify this property since the kernel will seek to take total
responsibility for the sizing of the SAFGrid. For example, the kernel will attempt to
make the SAFGrid match the size of the underlying frame. The kernel will also resize
the SAFGrid when the user resizes the form.
See Also
Height Property, Top Property, Width Property
120
Level Property
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFCheck, SAFCombo,
SAFOption
Description
Associates the control with a logical group of information contained within the
application.
Remarks
The Level property is related to, but not the same as, the Levels property of the
SAFUpdate control. The Levels property of the SAFUpdate control is used to define
all levels for a particular screen. Each data entry control must subsequently be
associated with one of these logical levels using its Level property. The Level property
can be modified at design time only; it cannot be modified at runtime.
For example, assume the Levels property of the SAFUpdate control contains the
following value:
TableA;N,TableB;D
In this example, TableA is the master table for first level so all controls displaying
information from TableA would have a value of 0 in their Level property. Level
numbers themselves always begin with zero and count upwards. Consequently all
controls displaying information from TableB would have a value of 1 in their Level
property.
If a particular control is one of the key fields for a particular level then a ,k should be
appended to the level number. For example, the control associated with
TableA.KeyField would have a value of 0,k in its Level property.
The last key field on Normal and Lookup levels must have either its PV or DBNav
property initialized as well as a corresponding PVChkFetch or DBNavFetch call in its
Chk event.
See Also
DVNav Property, Levels Property, PV Property, Chk Event, DBNavFetch
Functions, PVChkFetch Functions, Level_SetDefaults Statement
Reference
121
Levels Property
Applies To
SAFUpdate
Description
Defines an alias name and level type for all logical groups of information on the
applications screen.
Remarks
A level is defined as a set of fields from one or more tables which form a logical group.
In many cases, a one to one relationship exists between the number of levels and the
number of tables whose information is displayed on the screen. For example, if a
particular screen displays information from TableA, TableB and TableC then it is
likely that the screen will have three levels. This simply means that are three logical
groups of information being displayed on the screen.
The Levels property of the SAFUpdate control is used to define all levels for a
particular screen. It should not be confused with the Level property of individual data
entry controls. Each data entry control can only be associated with one of these logical
levels using its Level property.
Each level within a particular screen has a corresponding name and level type. The
Levels property should be a string expression in the following basic format:
AliasName0;LevelType0,AliasName1;LevelType1...,AliasName9;LevelType9
The AliasName name associated with any particular level will appear in places such as
the Insert/Delete dialog, Customization Manager, Templates and Copy Special (e.g.,
cut/copy/paste). Consequently, the AliasName should be a logical name that will have
meaning to users of the application.
The LevelType defines the navigational and display characteristics of a particular level.
The following table contains a list of valid level types:
Level Type
Description
Normal Level. Used in cases where one record at a time can be viewed such
as in Customer Maintenance or Employee Maintenance. Subsequent levels
inherit actions performed on a Normal level such as New and Delete.
122
Level Type
Description
DA
Constant Level. Used in cases where user entered key field(s) and/or database
navigation are not applicable since only one record is constantly displayed
on the screen. Typically used on Setup screens where only one record could
possibly be displayed on the screen. Also used on process screens having a
few data entry controls related to processing options.
The following table conceptually illustrates Levels property values for common
database relationships:
Table Names
Database Relationship
Levels Property
TableA
Header
TableAAlias;N
TableA
Detail
TableAAlias;D
TableA, TableB
Header, Detail
TableAAlias;N,TableBAlias;D
TableA
A maximum of two Normal Levels can be defined for any one application.
The Levels property can be modified at design time only; it cannot be modified at
runtime.
See Also
Level Property, DetailLoad Statement, Level_SetDefaults Statement, SetButton
Statement, SetLevelChg Statement, SqlCursor Statement, TestLevelChg Function
Reference
123
List Property
Applies To
SAFCombo
Description
Determines the fixed list of valid data values for the underlying field along with
corresponding descriptions.
Syntax
Value;Description [, Value;Description]...
Remarks
Combo Box controls are implemented for fields having a fixed list of valid choices. As
a user views a Combo Box control, various descriptive choices are shown which
should normally have meaning to any user of the application. However, each
description that the user views is actually associated with a corresponding data value.
This data value is normally a single character. When the user selects ChoiceA, the
value of the underlying data field is set to the data value which as been associated with
ChoiceA.
The List property allows the developer to enter all valid data values along with
corresponding viewable descriptions into a single property.
The List property can be modified at design time only; it cannot be modified at
runtime.
124
Mask Property
Applies To
SAFMaskedText
Description
Determines the type and number of characters that can be entered for a particular field.
Remarks
Each character in the Mask property corresponds to one character in the displayed
field. If a particular mask character is one of the supported mask types, then the
corresponding valid values will be permitted for that particular edit position.
Otherwise, the character is considered to be a string literal to be displayed within the
field. These string literals are display only, causing the cursor to automatically jump
over them during data entry. Furthermore, the string literals will not be stored in the
resulting value of the underlying data field since they are only for display purposes.
To modify the value of the Mask property at runtime, the SetProps statement should
be used, rather than modifying the property directly in VB code. Usage of SetProps
allows the system to track changes to property values, avoiding conflicts with
customizations.
The value of the Mask property can be narrowed at runtime but not expanded,
depending on the level at which the changes are being made (All User, One User, etc.).
See the Security section of the Customization Manager documentation.
The following table lists the supported mask types and their corresponding definition:
Mask Character
Description
Numeric (0-9)
See Also
SetProps Statement
Reference
125
Max Property
Applies To
SAFDate, SAFFloat, SAFInteger
Description
Determines the maximum valid value for the control.
Remarks
To modify the value of the Max property at runtime, the SetProps statement should be
used rather than modifying the property directly in VB code. Usage of SetProps allows
the system to track changes to property values so as to avoid conflicts with
customizations.
The value of the Max property can be customized to a lower value using the
Customization Manager. However, the Max property cannot be customized to a higher
value. See the Security section of the Customization Manager documentation.
See Also
DecimalPlaces Property, Min Property, SetProps Statement
126
Min Property
Applies To
SAFDate, SAFFloat, SAFInteger
Description
Determines the minimum valid value for the control.
Remarks
To modify the value of the Min property at runtime, the SetProps statement should be
used rather than modifying the property directly in VB code. Usage of SetProps allows
the system to track changes to property values so as to avoid conflicts with
customizations.
The value of the Min property can be customized to a higher value using the
Customization Manager. However, the Min property cannot be customized to a lower
value. See the Security section of the Customization Manager documentation.
See Also
DecimalPlaces Property, Max Property, SetProps Statement
MouseIcon Property
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFCheck, SAFCombo,
SAFOption
Description
Provides a custom icon that is used when the MousePointer property is set to 99.
Remarks
Use the MouseIcon property to load either cursor or icon files. Color cursor files such
as those shipped with Windows NT, are displayed in black and white. To display a
color cursor, use a color icon file (.ico). The MouseIcon property provides access to
custom cursors of any size, with any desired hot spot location. Visual Basic does not
load animated cursor (.ani) files, even though 32-bit versions of Windows support
these cursors.
This property can be modified at design time only; it cannot be modified at runtime.
See Also
MousePointer Property
Reference
127
MousePointer Property
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFCheck, SAFCombo,
SAFOption
Description
Returns or sets a value indicating the type of mouse pointer displayed when the mouse
is over a particular part of an object at run time.
Remarks
The object is a control. The value An integer specifying the type of mouse pointer
displayed, as described in the Microsoft Visual Basic Help. Summarized, a value of 0
causes the pointer type to be determined by the object it is over; a value of 1 is the
standard mouse arrow; a value of 99 causes the custom icon specified by the
MouseIcon property to be used as the mouse pointer.
This property is useful when you want to indicate changes in functionality as the
mouse pointer passes over controls on a form or dialog box.
This property can be modified at design time only; it cannot be modified at runtime.
See Also
MouseIcon Property
Name Property
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFGrid, SAFCheck,
SAFCombo, SAFOption, SAFUpdate
Description
Specifies the name used to reference the control from within code.
Remarks
The Customization Manager requires that all control names within a given application
be unique. This is because Customization Manager saves all changes made to a
particular control to the database, using the control name as a type of internal key. If an
object name is duplicated, Customization Manager will be not be able to correctly
resolve references to the corresponding controls.
Its also important to note that control names should not be modified after release of
the application. Customization Manager will not be able to apply customizations
referencing the old control name.
This property can be modified at design time only; it cannot be modified at runtime.
See Also
Index Property
128
NoteButton Property
Applies To
SAFMaskedText, SAFFloat, SAFInteger, SAFDate, SAFCombo, SAFGrid
Description
Returns or sets a value that determines the position of the Note button for the control.
Remarks
For the SAFGrid control, this property allows the developer to specify where the note
button for the grid should appear. Possible values are:
2 bottom right
3 top left
4 top right
5 none
1 left
2 right
If the value for the NoteButton property is set at the default for all controls on a level,
a note button will be placed to the right of the first key on the level, which is where
note buttons have traditionally been placed.
If the NoteButton property is set for two controls on a level, the note button will be
placed next to the first control in tab order. Tools for Visual Basic does not support
more than one note button per level.
The NoteButton property can also be set for controls in a detail level. In this case, the
note button will appear next to the control with the NoteButton property set when the
screen appears in form view.
See Also
NoteColumn property, HideNoteButtons statement
Reference
129
NoteColumn Property
Applies To
SAFGrid
Description
Returns or sets a value that determines if the Note column is or is not displayed in the
grid.
Remarks
This property allows the developer to specify that the first column in the grid should be
a note column. If a note exists for a detail line and this column is displayed, a note icon
will appear in the detail line. If the user wants to edit or create a note for a detail line,
they can open the note dialog by double-clicking in the note field for the particular
detail line. This column is only visible in grid view. When in form view, the user will
have to use the note button associated with the grid to display the note dialog.
See Also
NoteButton property, HideNoteButtons statement
130
PV Property
Applies To
SAFMaskedText
Description
Determines all possible values currently existing in the database.
Remarks
The PV property is conceptually similar to the List property of an SAFCombo control
in that it identifies possible data values for the relevant control. However, the PV
property is much more sophisticated in that these possible data values are actually
defined as existing data items contained within the database as opposed to a hardcoded list.
For example, many screens throughout the Solomon system require the entry of a valid
account number. Conceptually speaking, an account number is valid if a
corresponding record can be located within the Account database table. Thus, if we
wanted to determine if account number 001000 is a valid account number, we could do
so by issuing the following SQL Select statement:
Select * From Account
Where Acct LIKE '001000'
Order by Acct
If no record is returned by this simple SQL statement then 001000 is not an existing
account number and therefore would not be valid.
The PV property facilitates the determination of all possible values currently existing
in the database by allowing the developer to specify a relevant SQL statement or stored
procedure name.
In cases where the underlying application merely needs to insure that the key (e.g., ID)
of an existing data item is entered for a particular control, the relevant control simply
needs to contain a PV property. No code is necessary in this case since the application
does not need to manipulate the data record itself -- it only needs to make sure that
such a record does in fact exist.
However in cases where the application does need to manipulate the record identified
via the use of the PV property, one additional step is required. In particular the
application needs to explicitly fetch the record from within its Chk event using one of
the PVChkFetch functions. This will most commonly occur in the Chk event of the
last master key of Normal and Lookup levels - which is where the master table record
containing the requisite key field values is to be fetched from the database.
The end-user will be able to actually display the Possible Values window if an entry in
the PVRec table has been created with a PVId containing the same stored procedure
name as is specified in the SQL Proc/Text field of the PV property.
Reference
131
Description
SQL Proc/Text
Used to enter the SQL statement or stored procedure name whose result
set identifies all possible values currently existing in the database.
Constant
Wildcard
Struct.FieldName
Used in conjunction with the Parms to pass the value of other data items
as a runtime parameters to the SQL statement or stored procedure. The
Struct.FieldName value will normally be in the
bTableName.FieldName format. The portion of the entry that
identifies the table name MUST correspond precisely to the table name
string passed in a corresponding call to the SetAddr statement. For
example, assume the value of TableA.FieldA should be passed as a
runtime parameter to the stored procedure. In this case, the
Struct.FieldName would be bTableA.FieldA.
Declare Type
Length
Parm Tabs
Refresh the various data entry controls used to define parameters with
the current values of the particular parameter corresponding to the
selected tab. For example, to view the values for the second parameter
press the Parm2 tab.
132
= @parm1
Example 3
Select * from TableA
where TableA.StringFieldA
= @parm1
The first two examples use the LIKE statement for the last string field. However, since
the LIKE keyword does not apply to integer fields, the BETWEEN keyword is used for
integers. When the system handles wildcard values for a single integer parameter it
will automatically pass two parameters - the first having a value corresponding to
INTMIN and the last having a value corresponding to INTMAX.
The value of the underlying control is always passed to the SQL statement or stored
procedure as the LAST parameter. Consequently the last parameter does not need to be
manually defined using the Parm tabs. For example, if the stored procedure has only
one parameter then no parameters need to be manually defined within the PV property.
This is due to the fact that the value of the underlying control will automatically be
passed as the last parameter - which happens to be the only parameter in this particular
case.
The Order By clause must correspond to an index (i.e., it must not cause a temporary
sort operation) or else the view cannot be updated.
This property can be modified at design time only; it cannot be modified at runtime.
See Also
Chk Event, DBNav Property, FieldName Property, PVChkFetch Functions,
SetAddr Statement
Reference
133
Separator Property
Applies To
SAFFloat
Description
True/False property indicating whether the thousands separator should be displayed in
the control.
Remarks
When the property is set to True, numbers will display with thousand separators, as
shown in the following example: 123,456.78.
When the property is set to False, numbers will display without the thousand
separators, as shown in the following example: 123456.78.
The separator character is set from the Control PanelRegional Settings.
Spin Property
Applies To
SAFDate, SAFInteger
Description
True/False value indicating whether spin buttons should be displayed.
Remarks
To modify the value of the Spin property at runtime, the SetProps statement should be
used rather than modifying the property directly in VB code. Usage of SetProps allows
the system to track changes to property values so as to avoid conflicts with
customizations.
See Also
SpinIncrement Property
134
SpinIncrement Property
Applies To
SAFDate, SAFInteger
Description
Specifies the amount to increment or decrement a value when a spin button is used.
Remarks
To modify the value of the SpinIncrement property at runtime, the SetProps
statement should be used rather than modifying the property directly in VB code.
Usage of SetProps allows the system to track changes to property values so as to avoid
conflicts with customizations.
See Also
Spin Property
TabIndex Property
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFGrid, SAFCheck,
SAFCombo, SAFOption
Description
Determines the logical sequence of controls within their parent form.
Remarks
When the user presses Tab, the actual order of progression through the controls is
determined by the value of the TabIndex property specified during program
construction. There are however several exceptions to this general rule. In particular,
focus will skip over the control in the next tab sequence if it is either disabled or
invisible. Furthermore, the design time TabIndex property value can be modified
using the Customization Manager. This allows the logical sequence of data entry for
any particular screen to be customized for unique circumstances.
The TabIndex property is also used by API calls referencing a range of controls such
as: SetDefaults, SetProps and DispFields. These types of API calls allow the
application to specify the first and last control upon which the designated operation
should be performed. All controls having a TabIndex between the TabIndex of the
first control and the TabIndex of the last control will be included in the group of
targeted controls.
This property can be modified at design time only; it cannot be modified at runtime.
See Also
DispField Statements, SetDefaults Statement, SetProps Statement
Reference
135
TabStop Property
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFCheck, SAFCombo,
SAFOption, SAFGrid
Description
Indicates whether a user can use Tab to give the focus to an object.
Remarks
A value of True causes the control to be a tab stop. A value of False will cause focus to
skip over the field when the user is tabbing through controls.
The TabStop property differs from the Enabled property in that even if a particular
control is not a tab stop, the user can still set the focus to the control by clicking on it.
If a control is disabled then it cannot have focus under any circumstances.
To modify the value of the TabStop property at runtime, the SetProps statement
should be used rather than modifying the property directly in VB code. Usage of
SetProps allows the system to track changes to property values so as to avoid conflicts
with customizations.
See Also
Enabled Property, SetProps Statement
Tag Property
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFGrid, SAFCheck,
SAFCombo, SAFOption, SAFUpdate
Description
Specifies any additional data needed for an application program.
Remarks
To modify the value of the Tag property at runtime, the SetProps statement should be
used rather than modifying the property directly in VB code. Usage of SetProps allows
the system to track changes to property values so as to avoid conflicts with
customizations.
136
ToolTipText Property
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFCheck, SAFCombo,
SAFOption
Description
Returns or sets a tooltip. A tooltip is a small string of text that displays while the mouse
is positioned over the associated icon on a toolbar.
Remarks
To modify the value of the ToolTipText property at runtime, the SetProps statement
should be used rather than modifying the property directly in VB code. Usage of
SetProps allows the system to track changes to property values so as to avoid conflicts
with customizations.
Note: Do not use this property with the SAFGrid control.
Grid-view tooltips are driven by the ToolTipText property on the form-view controls.
If the current columns form-view partner has a value for the ToolTipText property,
that value will be used.
Reference
137
Top Property
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFCheck, SAFCombo,
SAFGrid, SAFOption, SAFUpdate
Description
Determines the distance between the top edge of a control and the top edge of its
container object.
Remarks
To avoid potential conflicts with customizations applied at runtime using the
Customization Manager, do not modify the position of a control at runtime.
The Top property of the SAFGrid control exists at both design and run time.
However, it can be modified only at design time. When you put an SAFGrid on a form
at design-time, it will have values for the sizing properties (Left, Top, Height, Width).
You can modify these values to optimize the size of the grid for design-time viewing.
You can size the grid quite small and put it in the lower-right corner of the frame in
which the SAFGrid resides to make it easier to see and/or manipulate all of the formview controls to which the SAFGrid will be bound.
At runtime however, do not modify this property. The kernel will seek to take
responsibility for the sizing of the SAFGrid. For example, the kernel will attempt to
make the SAFGrid match the size of the underlying frame. The kernel will also resize
the SAFGrid when the user resizes the form.
See Also
Height Property, Left Property, Width Property
138
Trigger Property
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFCheck, SAFCombo,
SAFOption
Description
Used to specify a list of one or more source fields upon which the value of the current
control is dependent.
Syntax
SourceTable.Field; CalculationType; ErrorCheckType [,SourceTable.Field;
CalculationType; ErrorCheckType]...
Remarks
A single field can be a identified as a source field in the Trigger property of multiple
controls. Correspondingly, a single control can have many source fields specified in its
Trigger property.
A Trigger is activated whenever the value of any of the source fields is changed either by the user or when any of the corresponding controls are re-defaulted (via calls
such a SetDefaults or as a result of a New operation).
Programmatic modification of the underlying field value does not activate the Trigger.
The value of the underlying control will automatically be re-displayed if it is changed
as a result of the Trigger.
The Trigger Field Specifications dialog contains a single text box into which the
source field, calculation type and error checking option is entered for all fields upon
which the value of the underlying control is dependent.
The Source Field Name portion of any one trigger definition specifies the data item
which, when changed, activates the Trigger. This value should be in the
bTableName.FieldName format. The portion of the entry that identifies the table
name MUST correspond precisely to the table name string passed in a corresponding
call to the SetAddr statement. For example, assume the value of the current control is
dependent upon the value of TableA.FieldA. In this case, the Source Field Name would
be bTableA.FieldA.
Reference
139
Description
140
Description
If the underlying field is the source field for any other Trigger property, it will be error
checked immediately regardless of the Error Checking option specified in its Trigger
property. This situation is referred to as a nested trigger. The reason nested trigger
fields are always error checked immediately is that the underlying field of the second
trigger depends on the accuracy of the value in its source field. If the Chk event of the
first field is not immediately executed, it is possible the underlying field of the second
trigger would use a bad value. Correspondingly, if an error occurs during the Chk
event of the first field then the second trigger will not be activated since by definition
its source field contains an erroneous value. When the user subsequently enters a valid
value in the first field, the second trigger will be activated.
For example, Customer ID is a trigger source for Terms ID. Terms ID is a trigger
source for Discount Date. When Customer ID is changed its Chk event is executed. If
its Chk event finds no error, the first trigger executes and sets the value of Terms ID.
Since Terms ID is also a source field for the Discount Date trigger, its Chk event is
also executed. Its Chk event loads the corresponding terms record and if no errors
occur, the Discount Date trigger is executed. This trigger sets the value of Discount
Date. The Discount Date is marked for a later error check, since it is not a source field
for any other triggers.
This property can be modified at design time only; it cannot be modified at runtime.
See Also
Chk Event, Default Event, Default Property, SetAddr Statement
Reference
141
TrueText Property
Applies To
SAFCheck, SAFOption
Description
Determines the value of the underlying data field whenever the check box / option
button is checked / selected.
Remarks
Normally the TrueText value for integer true/false type of fields (i.e., check box
controls) is 1. This allows the value to more easily be tested for a true value within
SQL. It also corresponds to the value of the LTRUE symbolic constant declared in
Applic.DH. It does not however correspond to the value of True within VB - which has
a value of -1.
This property can be modified at design time only; it cannot be modified at runtime.
See Also
FalseText Property
142
Visible Property
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFCheck, SAFCombo,
SAFOption, SAFGrid
Description
Determines whether or not the control is visible.
Remarks
A value of True indicates that the control is visible whereas a value of False causes the
control to be invisible.
Required fields should not be made invisible unless they are automatically defaulted
with a valid value.
To modify the value of the Visible property at runtime, the SetProps statement should
be used rather than modifying the property directly in VB code. Usage of SetProps
allows the system to track changes to property values so as to avoid conflicts with
customizations.
If a control is made invisible by the application then it cannot be made visible using the
Customization Manager. However if a control is made visible by the application then it
can be made invisible by the Customization Manager.
The following remarks relate to how the Visible property relates to the SAFGrid
control. At runtime, Solomon forces the grid to be visible during initialization. Do not
set this property at design time for the SAFGrid control. Likewise, do not call
SetProps() on a form-view control because that reveals an intent to modify the Visible
property on a row-by-row type of basis, which is not supported.
The only appropriate runtime modification to the visibility of a grid component is to
display or hide an entire column, based on a data-driven rule. For example, suppose the
Application A contains a grid having 10 fields. Let us also suppose that fields 7, 8, 9
and 10 should not be viewable unless Module XYZ is installed and configured. Lastly,
let us assume that Module XYZ is neither installed nor configured. This would mean
that Application A needs to hide fields 7, 8, 9 and 10. Since these fields are associated
with an SAFGrid, we would want to hide the grid columns that correspond to fields 7,
8, 9 and 10. This operation can be performed during Form_Load by calling
MSetProp() for each of the fields to be hidden -- each time specifying a value of False
for the Visible property. Note that in the MSetProp() scenario, this call must be made
before the SAFGrid receives focus (such as at screen load, or in a master key Chk
event of a header level). Do not call MSetProp() from within SAFGrid events, such as
LineGotFocus().
To hide an SAFGrid, set the Visible property of the underlying frame to False.
See Also
BlankErr Property, Enabled Property, MSetProp Statement, SetProps Statement
Reference
143
WhatsThisHelpID Property
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFCheck, SAFCombo,
SAFOption
Description
Returns or sets an associated context number for an object. Use to provide contextsensitive Help for your application using the Whats This pop-up in Windows 95 Help.
Remarks
Do not use this property with the SAFGrid control. Grid-view help is driven by
properties on the form-view controls. If the current columns form-view partner has a
help context, that value will be used. Otherwise, the help context of the form-view
container (e.g., the frame) will be used.
To modify the value of the WhatsThisHelpID property at runtime, the SetProps
statement should be used rather than modifying the property directly in VB code.
Usage of SetProps allows the system to track changes to property values so as to avoid
conflicts with customizations.
See Also
HelpContextID Property, ShowWhatsThis Method
144
Width Property
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFCheck, SAFCombo,
SAFOption, SAFGrid
Description
Determines the dimensions of the control.
Remarks
To avoid potential conflicts with customizations applied at runtime using the
Customization Manager, do not modify the dimensions of a control at runtime.
The following remarks relate to how the Width property functions when used with the
SAFGrid control. The Width property exists at both design-time and runtime,
however, it can be modified only at design time.
When you put an SAFGrid on a form at design-time, it will have values for the sizing
properties (Left, Top, Height, Width). You can modify these values to optimize the
size of the grid for design-time viewing. You can size the grid quite small and put it in
the lower-right corner of the frame in which the SAFGrid resides to make it easier to
see and/or manipulate all of the form-view controls to which the SAFGrid will be
bound.
At runtime however, do not modify this property. The kernel will seek to take total
responsibility for the sizing of the SAFGrid. For example, the kernel will attempt to
make the SAFGrid match the size of the underlying frame. The kernel will also resize
the SAFGrid when the user resizes the form.
See Also
Height Property, Left Property, Top Property
Reference
145
Events
Cancel Event
Applies To
SAFUpdate
Description
Occurs when the user clicks the Cancel button on the Solomon toolbar.
Syntax
Sub Update1_Cancel(Level, RetVal)
Remarks
When the user clicks the Cancel button on the Solomon toolbar, the Cancel event is
called once for each level in order from LEVEL0 to LEVELn.
This event is normally used on single Constant level applications, such as Setup
screens. These types of applications do not have key fields which can be re-executed in
order to re-fetch the currently displayed information. Consequently, the Cancel event
provides the application with an opportunity to re-fetch the Constant level record (e.g.,
For example, the setup record).
The Cancel event uses the following arguments:
Argument
Type
Description
Level
Integer
RetVal
Integer
146
Example
The following example illustrates how the Payroll Setup screen has implemented the
Cancel event.
Sub Update1_Cancel (level%, retval%)
Dim PRSetup_Fetch
As Integer
'Initialize bPRSetup
PRSetup_Fetch = SqlFetch1(CSR_PRSetup, "PRSetup_All",
bPRSetup,
LenB(bPRSetup))
If (PRSetup_Fetch = 0) Then
'Display fields from existing PRSetup record
Call DispFields(PNULL, PNULL, PNULL)
Else
'Default all controls for insert mode
Call SetDefaults(PNULL, PNULL, PNULL)
End If
End Sub
Reference
147
Chk Event
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFCheck, SAFCombo,
SAFOption
Description
Occurs, at a minimum, whenever the data field changes and loses focus.
Syntax
Sub CtrlName_Chk( [Index], ChkStrg, RetVal)
Remarks
Whenever the user modifies the value of a field, the new value often needs to be
validated (e.g., checked for errors). If the new data value is valid then the application
may perform other related operations such as re-default or disable other fields. The
Chk event is where such code normally resides since this event is called anytime the
value of the field is changed.
The Chk event can also fire at other times when the user did not directly modify the
value of the control. For example, navigating through existing records on a Normal
level using the First, Last, Prev, and Next toolbar buttons is conceptually equivalent to
the user entering new key field values to bring up different records. Consequently,
when navigating through existing records on a Normal level, the Chk event for each
key field on that Normal level is fired every time the user navigates from one record to
the next - regardless of how the navigation operation was invoked (e.g., data entry or
toolbar navigation). The Chk event can also fire in relation to the Trigger property.
For example, using the Trigger property, a relationship between FieldA and FieldB
can be defined such that FieldB should be re-validated (e.g., its Chk event should be
called) anytime the value of FieldA changes.
The Chk event uses the following arguments:
Argument
Type
Index
Description
ChkStrg
String
RetVal
Integer A data value can be rejected simply by modifying the RetVal parameter
which is passed to the Chk event. This parameter is actually passed by
reference which means that any modifications to RetVal are automatically
detected by the system once program control exits the Chk event.
If the user just typed a new value for the field and pressed Tab, then
ChkStrg will correspond to that new data value. If the Chk event was
called for any other reason, such as navigation, triggers, etc., then the
value of ChkStrg is the data value that will be assigned to the underlying
field unless it is rejected within the Chk event. In this latter case, it is
possible that the value of the field will be unchanged and therefore
ChkStrg will reflect that fact.
148
Description
NoAutoChk
A Message Number
ErrNoMess
This return value is similar to a message number in the fact that it will
cause the value of ChkStrg to be rejected. However the system will not
display a message since the application should already have done so
during the Chk event. This is useful in cases where the message requires
data values for one or more replacement parameters. Consequently, the
application can use the Messf statement to display the message along
with the required substitution values and then subsequently set RetVal =
ErrNoMess.
The Chk event for the last master key of Normal and Lookup levels must contain
either a PVChkFetch or DBNavFetch call depending on whether a PV or DBNav
property was implemented.
If a data entry control has a PV property value and no code within its Chk event, then
the system will automatically validate the value of ChkStrg using the PV property. If
the corresponding record does not exist then the value of ChkStrg will automatically be
rejected and a not found type of message will be displayed.
See Also
DBNavFetch Functions, Level Property, Messf Statement, PVChkFetch
Functions, Trigger Property
Reference
149
Example
The following example illustrates a common implementation of the Chk event on the
last master key for a Normal level. This particular example was taken from the Payroll
Earnings Type Maintenance screen. Notice the fact that RetVal is set to NoAutoChk.
This allows new Earnings Types to be defined even though the PVChkFetch call
returned NOTFOUND to the application.
Sub cID_Chk (chkstrg As String, retval As Integer)
Dim EarnType_Fetch
As Integer
The following example illustrates the Chk event, on a non-key field control, in which a
record corresponding to the value of ChkStrg must be fetched from the database for use
by the application. If the record cannot be found then it is to be considered an error.
This code snippet was actually taken from the Chk event of the Earnings Type field on
the Timesheet Defaults sub-screen of the Payroll Employee Maintenance screen. This
particular application requires that the default Earnings Type for all employees must
contribute to net pay. Thus it is not enough that the user enters the ID of just any
Earnings Type. Rather, that Earnings Type must also be defined as contributing to net
pay. If the relevant Earnings Type does not contribute to net pay then it will be rejected
simply by setting RetVal to the particular Solomon message number explaining the
nature of the problem.
150
Reference
151
Default Event
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFCheck, SAFCombo,
SAFOption
Description
Occurs anytime the control is being defaulted and a Default property has not been
implemented.
Syntax
Sub CtrlName_Default( [Index], OldValue, RetVal)
Remarks
The default data value for any particular data entry control can be specified via either
the Default property or the Default event. The Default property can be used when the
default value is not contingent upon any the value of any other data item. However, if
the methodology for determining a default value varies depending particular situations,
then code should be written for the Default event. If a Default property is defined then
the Default event will not be used.
Within the Default event, the default value of the relevant field is set by referring
directly to the VB variable to which the control is bound. For example, if the control is
bound to string field called bTableA.FieldA within its FieldName property then
within the Default event the value of the field can be defaulted in a manner such as
bTableA.FieldA = StringValue. The default data value for an SAFOption button
group is always derived from the first option button in the group, since by definition
only one option button can be selected within any particular group. Consequently, the
Default event is only called for Index zero.
The Default event uses the following arguments:
Argument
Type
Description
Index
Integer
OldValue
String
RetVal
Integer
See Also
Default Property, Level_SetDefaults Statement, SetDefaults Statement, Trigger
Property
152
Delete Event
Applies To
SAFUpdate
Description
Occurs during the series of actions/events initiated by a DELETE operation.
Syntax
Sub Update1_Delete( Level, LevelsDone, RetVal)
Remarks
To understand when the Delete event occurs, a developer must first understand the
higher level concept of what is referred to here as a DELETE operation. The operation
is differentiated from the event in the fact that the Delete event comprises only a
segment of a series of events implied by a DELETE operation.
A DELETE operation is initiated when the user clicks on Delete on the Solomon
toolbar. The only exception is when the user deletes a detail line from an SAFGrid in
which case the LineChk event is called.
A DELETE operation is comprised of the following series of actions and/or events. If
the application contains more than one Normal level then the user will be prompted as
to which of the Normal level records is being deleted. Processing will begin with the
level the user selects and continue for each non-Lookup level in order from LEVEL0 to
LEVELn.
The Delete event is called for the level. If this is the first level to be processed than
a database transaction has not yet been initiated. Consequently the application
must call TranBeg if it needs to perform database update/delete operations during
the first pass through the Delete event.
If the application did not modify the value of RetVal in the preceding step then the
master table for the level is deleted. The master table for any particular level is the
table identified by the SetAddr call for that particular level.
Once all levels which had previously been modified have been successfully updated,
the database transaction is ended and a NEW operation is automatically initiated to
prepare the application for data entry.
If any errors occur during the delete of any level then the entire operation is aborted including the database transaction.
Reference
153
Type
Description
Level
Integer
LevelsDone
Integer
RetVal
Integer
See Also
LineChk Event, SetAddr Statement, TranBeg Statement
Example
The following example illustrates how to perform delete logic within the Delete event
and abort the entire DELETE operation if any logical errors are detected. This
particular code snippet relates to the Payroll Employee Maintenance screen. Notice the
fact that an Employee record cannot be deleted if they have any year-to-date earnings.
This is accomplished by setting RetVal to Solomon message number 259. This will not
only cause the entire DELETE operation to be aborted but it will also cause the
corresponding Solomon message to be displayed - thereby explaining the precise
nature of the problem to the user. The actual message text associated with this message
number is Year-To-Date earnings must be zero. Similarly, an Employee cannot be
deleted if he/she has any existing checks or timesheet transactions. In these cases,
RetVal is set to 58 which has the following corresponding Solomon message text:
This record cannot be deleted. It is in use elsewhere in the system.
As String
Dim PRDoc_Fetch
As Integer
Dim PRTran_Fetch
As Integer
154
Reference
DragDrop Event
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFGrid, SAFCheck,
SAFCombo, SAFOption
Description
This event is reserved for Microsoft Business Solutions and should not be used.
DragOver Event
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFGrid, SAFCheck,
SAFCombo, SAFOption
Description
This event is reserved for Microsoft Business Solutions and should not be used.
155
156
Finish Event
Applies To
SAFUpdate
Description
Occurs when the user indicates he/she is finished with the information currently
displayed on the screen.
Syntax
Sub Update1_Finish (Level, Updated, RetVal)
Remarks
The Finish event is called when the user is finished with the currently displayed
information so as to allow the application an opportunity to perform specific operations
on or related to the data before it leaves the users screen. For example, assume the
user just entered some sort of financial information and now he/she is simply going to
close the application since they have completed their original task. At that point the
application could warn the user that the information is out of balance and ask whether
or not they want to remedy the problem. Without such a warning, the user may not
notice the error until it subsequently causes some other problem.
The user is considered to be finished with the currently displayed information when
they perform any one of the following operations:
When the user clicks on the Finish button on the Solomon toolbar. In this case, the
Finish event actually fires after the Update event - if a SAVE operation is even
necessary (e.g., if any information changed).
When the user attempts to either enter a new item, navigate to a different item or
close the screen. If information has been changed then the user will first be
prompted as to whether or not they want to save their outstanding changes. If not
then the screen will be refreshed with the information as it exists in the database so
that accurate data is readily available when the Finish event is called.
The Finish event is called once for each level in order from LEVELn to LEVEL0.
Notice that this event is called in reverse order as compared to the NewLevel, Update,
Delete and Cancel events. This reverse order allows the application to report problems
with the data at the most granular level first.
The application can abort the Finish event by merely changing the RetVal parameter.
In this case, the users action is also aborted. For example, assume the user has RecordA
on the screen and then clicks Next on the Solomon toolbar. Clearly this indicates that
the user is finished viewing RecordA and now wants to view the next record presumably RecordB. Consequently, the Finish event is called just prior to navigating
to RecordB. If the application sets RetVal, say to a Solomon message number, then the
corresponding message will be displayed when the Finish event for the current level
exits and the navigate operation will be aborted. Since the navigate operation was
aborted, the user will still be able to view RecordA.
Reference
157
Type
Description
Level
Integer
Updated
Integer
RetVal
Integer
GotFocus Event
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFGrid, SAFCheck,
SAFCombo, SAFOption
Description
Occurs whenever an object receives focus.
Syntax
Sub object_GotFocus([index As Integer])
Remarks
The object is the control. The index As Integer identifies the object if it is in a control
array.
Use this event to specify the actions that need to occur when a control first receives the
focus. An object can receive the focus only if its Enabled and Visible properties are
set to True.
See Also
Enabled Property, Visible Property
158
LineChk Event
Applies To
SAFGrid
Description
Occurs whenever a detail line within an SAFGrid control is either inserted, updated or
deleted.
Syntax
Sub SAFGridName_LineChk( Action, RecMaintFlg, RetVal)
Remarks
Any time the user inserts, updates or deletes a detail line in an SAFGrid control, the
LineChk event fires. In the insert and update cases, the event does not actually execute
until the user actually leaves the detail line.
This event is most often used to perform special delete logic for detail lines that the
user is attempting to delete. For example, the General Ledger Chart of Accounts
Maintenance screen contains a grid displaying all records from the Account table.
Users can delete Account records provided that the corresponding account number is
not used on any setup screens among other areas. This is actually implemented via the
use of logic within the LineChk event.
Deleted records are copied from the underlying memory array to a temporary deleted
record memory array. The resource handle to that memory array can be obtained
using the MGetDelHandle function.
The LineChk event uses the following arguments:
Argument
Type
Description
Action
Integer
RecMaintFlg
Integer
RetVal
Integer
Applic.DH contains the following symbolic constants defining possible Action values:
Constant
Description
INSERTED
UPDATED
DELETED
Reference
159
Description
NEWROW
Indicates that the current detail line is just now being added. The status of
the detail line will be changed to INSERTED if no errors occur during the
LineChk event. If any further actions are performed on the same detail
line, then when LineChk subsequently executes it will have a
RecMaintFlg of INSERTED.
INSERTED
The current detail line was previously added after the SAFGrid was
initially loaded but has not yet been saved to the database.
UPDATED
The current detail line was initially loaded into the SAFGrid but has been
subsequently modified. Furthermore, the modifications to the current detail
line have not yet been saved.
NOTCHANGED
The current detail line was initially loaded into the SAFGrid and has not
been previously modified. Note: Records marked as INSERTED and
UPDATED will automatically be assigned the NOTCHANGED status
after the next successful SAVE operation.
See Also
LineGotFocus Event, MGetDelHandle Function, SetButton Statement
160
LineGotFocus Event
Applies To
SAFGrid
Description
Occurs whenever a detail line within an SAFGrid control receives focus.
Syntax
Sub SAFGridName_LineGotFocus( RecMaintFlg, RetVal)
Remarks
Any time the user moves to or inserts a detail line within an SAFGrid control, the
LineGotFocus event is called immediately.
The RecMaintFlg parameter can subsequently be evaluated to determine whether or
not the user is actually adding a new detail line. In such a case, default values can be
explicitly assigned to fields within the detail record for which no corresponding control
exist. For example, assume TableA is a header table and TableB is a detail record. In
this case, each unique TableA record could have many unique TableB records
displayed within the SAFGrid. However, the primary point to make here is that the
first segment of the unique key for TableB would have to include a field that relates
directly to TableA (e.g., the join field). This type of field is a prime candidate to be
defaulted in the LineGotFocus event since it will always have the same value (e.g., the
value of TableA.KeyField) and therefore creating an invisible control with a Default
property is not really necessary.
The LineGotFocus event uses the following arguments:
Argument
Type
Description
RecMaintFlg
Integer
RetVal
Integer
Reference
161
Description
NEWROW
INSERTED
The current detail line was successfully added after the SAFGrid
was loaded and has not been saved to the database.
UPDATED
The current detail line was initially loaded into the SAFGrid but
has been subsequently modified. Furthermore, the modifications to
the current detail line have not yet been saved.
NOTCHANGED
The current detail line was initially loaded into the SAFGrid and
has not been subsequently modified. Note: Records marked as
INSERTED and UPDATED will automatically be assigned the
NOTCHANGED status after the next successful SAVE operation.
See Also
LineChk Event, SetButton Statement
Example
The following example is taken from the Payroll Earnings Type Maintenance screen.
This screen is a header/detail type of screen having the EarnType table as the header
table and two detail records in the grid - namely ValEarnDed and Deduction.
ValEarnDed is the master table for the detail level and the Deduction table is only
joined in for a description. At any rate, notice the test for NEWROW and the
corresponding work that is only performed for new detail lines.
Sub Spread_ValEarnDed_LineGotFocus (maintflg%, retval%)
If (maintflg = NEWROW) Then
'Null out secondary records on the detail line
bDeduction = nDeduction
'Initialize the master detail record with the key field ID from the
'header record
bValEarnDed.EarnTypeId = bEarnType.Id
End If
End Sub
162
LostFocus Event
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFGrid, SAFCheck,
SAFCombo, SAFOption
Description
Occurs whenever an object loses the focus, either by user action, or by changing the
focus in code using the ApplSetFocus statement.
Syntax
Sub object_LostFocus([index As Integer])
See Also
ApplSetFocus Statement, GotFocus Event
MemoryLoad Event
Applies To
SAFUpdate
Remarks
This event is reserved for use by Microsoft Business Solutions and should not be used.
Reference
163
MouseDown Event
Applies To
SAFDate, SAFFloat, SAFInteger, SAFCheck, SAFMaskedText, SAFOption
Description
Occurs whenever a user presses a mouse button.
Syntax
Sub object_MouseDown([index As Integer,]button As Integer, shift As Integer, x As
Single, y As Single)
Remarks
The MouseDown event has the following parts:
Part
Description
object
index
button
shift
x, y
164
Value
Description
vbLeftButton
vbRightButton
vbMiddleButton
Constant (Shift)
Value
Description
vbShiftMask
VbCtrlMask
VbAltMask
The constants then act as bit masks you can use to test for any combination of buttons
without having to figure out the unique bit field value for each combination.
You can use MouseMove to respond to an event caused by moving the mouse. The
button argument for MouseDown and MouseUp differs from the button argument
used for MouseMove. For MouseDown and MouseUp, the button argument indicates
exactly one button per event, whereas for MouseMove, it indicates the current state of
all buttons.
The constants then act as bit masks you can use to test for any combination of buttons
without having to figure out the unique bit field value for each combination.
Use MouseMove to respond to an event caused by moving the mouse. The button
argument for MouseDown and MouseUp differs from the button argument used for
MouseMove. For MouseDown and MouseUp, the button argument indicates exactly
one button per event, whereas for MouseMove, it indicates the current state of all
buttons.
See Also
MouseMove Event
Reference
165
MouseMove Event
Applies To
SAFDate, SAFFloat, SAFInteger, SAFCheck, SAFMaskedText, SAFOption
Description
Occurs whenever a user drags the mouse.
Syntax
Sub object_MouseMove([index As Integer,] button As Integer, shift As Integer, x As
Single, y As Single)
Remarks
Part
Description
object
Index
Button
Shift
An integer that corresponds to the state of the Shift, Ctrl, and Alt
keys. A bit is set if the key is down. The shift argument is a bit field with
the least-significant bits corresponding to the Shift key (bit 0), the
Ctrl key (bit 1), and the Alt key (bit 2 ). These bits correspond to the
values 1, 2, and 4, respectively. The shift argument indicates the state of
these keys. Some, all, or none of the bits can be set, indicating that some,
all, or none of the keys are pressed. For example, if both Ctrl and Alt
were pressed, the value of shift would be 6.
X, y
A number that specifies the current location of the mouse pointer. The x
and y values are always expressed in terms of the coordinate system set by
the ScaleHeight, ScaleWidth, ScaleLeft, and ScaleTop properties of the
object.
166
MouseUp Event
Applies To
SAFFloat, SAFInteger, SAFCheck, SAFMaskedText, SAFOption
Description
Occurs whenever a user releases the mouse button.
Syntax
Sub object _MouseUp([index As Integer,]button As Integer, shift As Integer, x As
Single, y As Single)
Remarks
The MouseUp event has the following parts:
Part
Description
object
Index
Button
An integer that identifies the button that was pressed (MouseDown) or released
(MouseUp) to cause the event. The button argument is a bit field with bits
corresponding to the left button (bit 0), right button (bit 1), and middle button (bit
2). These bits correspond to the values 1, 2, and 4, respectively. Only one of the
bits is set, indicating the button that caused the event.
Shift
An integer that corresponds to the state of the Shift, Ctrl, and Alt keys when
the button specified in the button argument is pressed or released. A bit is set if
the key is down. The shift argument is a bit field with the least-significant bits
corresponding to the Shift key (bit 0), the Ctrl key (bit 1), and the Alt key
(bit 2 ). These bits correspond to the values 1, 2, and 4, respectively. The shift
argument indicates the state of these keys. Some, all, or none of the bits can be
set, indicating that some, all, or none of the keys are pressed. For example, if both
Ctrl and Alt were pressed, the value of shift would be 6.
X, y
A number that specifies the current location of the mouse pointer. The x and y
values are always expressed in terms of the coordinate system set by the
ScaleHeight, ScaleWidth, ScaleLeft, and ScaleTop properties of the object.
Use MouseDown or MouseUp to specify actions that will occur when a given mouse
button is pressed or released. Unlike the Click and DblClick events, MouseDown and
MouseUp events enable you to distinguish between the left, right, and middle mouse
buttons. You can also write code for mouse-keyboard combinations that use the
Shift, Ctrl, and Alt keyboard modifiers.
Constant (Button)
Value
Description
vbLeftButton
VbRightButton
VbMiddleButton
Reference
Constant (Shift)
Value
Description
vbShiftMask
vbCtrlMask
vbAltMask
167
The constants then act as bit masks you can use to test for any combination of buttons
without having to figure out the unique bit field value for each combination.
You can use MouseMove to respond to an event caused by moving the mouse. The
button argument for MouseDown and MouseUp differs from the button argument
used for MouseMove. For MouseDown and MouseUp, the button argument indicates
exactly one button per event, whereas for MouseMove, it indicates the current state of
all buttons.
The constants then act as bit masks you can use to test for any combination of buttons
without having to figure out the unique bit field value for each combination.
See Also
MouseMove Event
168
NewLevel Event
Applies To
SAFUpdate
Description
Occurs during the series of actions/events initiated by a NEW operation.
Syntax
Sub Update1_NewLevel( Level, RetVal)
Remarks
To understand when the NewLevel event occurs, a developer must first understand the
higher level concept of what is referred to here as a NEW operation. The operation is
differentiated from the event in the fact that the NewLevel event comprises only a
segment of a series of events implied by a NEW operation.
A NEW operation is initiated by any one of the following occurrences:
When the user clicks on the New button on the Solomon toolbar.
When the user clicks on the Finish button on the Solomon toolbar. In this case, the
NewLevel event actually fires after the Update and Finish events complete
successfully.
When the user clicks on the Delete button on the Solomon toolbar. After the record
is successfully deleted in the Delete event, the application prepares itself to receive
new information by automatically initiating a NEW operation.
When the user navigates either prior to the first record or past the last record in a
table using either the Prev or Next buttons on the Solomon toolbar.
When the user enters a value that does not already exist in the database for one or
more key fields. For example, if an application contains three key fields then a
NEW operation will be initiated if the combination of all three key field values
does not already exist in the database.
A NEW operation is comprised of the following series of actions and/or events for
each non-detail level - beginning with the level on which the new operation was
initiated. For example, if the NEW operation is initiated on LEVEL0, the levels will be
processed in order from LEVEL0 to LEVELn.
The master table for the level is blanked out. The master table for any particular
level is the table identified by the SetAddr call for that particular level.
Since defaulting for new detail level records within an SAFGrid control is performed
within the LineGotFocus event, the NewLevel event is not called for detail levels.
Reference
169
Type
Description
Level
Integer
RetVal
Integer
See Also
Level_SetDefaults Statement, LineGotFocus Event, ScreenInit Statement,
SetAddr Statement
Example
The following code snippet was taken from the Payroll Employee Maintenance screen.
Sub Update1_NewLevel (level%, retval%)
If (level = LEVEL0) Then
'Force ALL default values to be applied to EMPLOYEE level BEFORE
'Evaluate_Properties() is called.
Call Level_SetDefaults(PNULL, PNULL, PNULL, LEVEL0)
bEmployee.CalQtr = bPRSetup.CurrCalQtr
bEmployee.CalYr = bPRSetup.CurrCalYr
'Re-evaluate the properties of all controls whose property settings
'depend upon data values.
Call Evaluate_Properties(FLD_ALL)
'Set retval to keep Swim from defaulting LEVEL0 controls again.
RetVal = NoAction
End If
End Sub
170
Update Event
Applies To
SAFUpdate
Description
Occurs during the series of actions/events initiated by a SAVE operation.
Syntax
Sub Update1_Update( Level, InsertFlg, LevelsDone, LevelsLeft, RetVal)
Remarks
To understand when the Update event occurs, a developer must first understand the
higher level concept of what is referred to here as a SAVE operation. The operation is
differentiated from the event in the fact that the Update event comprises only a
segment of a series of events implied by a SAVE operation.
A SAVE operation is initiated by any one of the following occurrences:
When the user clicks on the Save button on the Solomon toolbar.
When the user clicks on the Finish button on the Solomon toolbar.
When the user answers Yes in response to the Do you want to save your
outstanding changes? prompt. This prompt occurs anytime the user has modified
data and then attempts to either enter a new item, navigate to a different item or
close the screen without first saving his/her changes.
A SAVE operation is comprised of the following series of actions and/or events for
each level which has been changed in order from LEVEL0 to LEVELn. For example,
if the only information that changed resides on LEVEL0 then only LEVEL0 will be
processed during the SAVE operation. A database transaction is started before any
levels are processed.
If the application did not modify the value of RetVal in the preceding step then the
master table for the level is updated. The master table for any particular level is the
table identified by the SetAddr call for that particular level.
Once all levels which had previously been modified have been successfully updated,
the database transaction is ended. The Update event is then called one additional time.
The Level parameter will have a value corresponding to the Finished symbolic constant
defined in Applic.DH. At this point the level status for all levels should have a value of
NOTCHANGED. Furthermore, the line status of each individual detail line within any
grids should also have a value of NOTCHANGED.
Reference
171
If any errors occur during the update of any level then the entire operation is aborted including the database transaction.
The Update event uses the following arguments:
Argument
Type
Description
Level
Integer
InsertFlg
Integer
LevelsDone
Integer
LevelsLeft
Integer
RetVal
Integer
See Also
MGetLineStatus Function, SetLevelChg Statement, TestLevelChg Function
172
Methods
AboutBox Method
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFCombo, SAFCheck,
SAFGrid, SAFOption, SAFUpdate
Description
Displays the About Box. The About Box is usually used to identify the version of
software.
Drag Method
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFCombo, SAFCheck,
SAFGrid, SAFOption
Description
This method is reserved for Microsoft Business Solutions and should not be used.
Move Method
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFCombo, SAFCheck,
SAFGrid, SAFOption
Description
This method is reserved for Microsoft Business Solutions and should not be used.
SetFocus Method
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFCombo, SAFCheck,
SAFGrid, SAFOption
Description
This method is reserved for Microsoft Business Solutions and should not be used. Use
the ApplSetFocus() API instead.
Reference
173
ShowWhatsThis Method
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFCombo, SAFCheck,
SAFGrid, SAFOption
Description
Displays a selected topic in a Help file using the Whats This popup.
Syntax
object.ShowWhatsThis
Remarks
The object placeholder represents an object expression that evaluates to an object. The
ShowWhatsThis method is useful for providing context-sensitive Help from a context
menu in your application. The method displays the topic identified by the
WhatsThisHelpID property of the object specified in the syntax.
See Also
WhatsThisHelpID Property
ZOrder Method
Applies To
SAFDate, SAFFloat, SAFInteger, SAFMaskedText, SAFCombo, SAFCheck,
SAFGrid, SAFOption
Description
This method is reserved for Microsoft Business Solutions and should not be used.
174
Syntax
ParmValue = ApplGetParms()
Remarks
The ApplGetParms statement can be used to retrieve parameters which were
originally passed by another Tools for Visual Basic application using either the
CallApplic or CallApplicWait statement. Multiple parameters can be retrieved by
making successive calls to ApplGetParms.
If the calling application passed parameters via named parameter sections, using the
ApplSetParmValue statement in conjunction with either the CallApplic or
CallApplicWait statement, then ApplGetParms will only be able to retrieve
parameters from the default VBRDT section. The ApplGetParmValue function is the
only means by which the called application can retrieve parameters from any named
parameter section other than the default VBRDT section.
The ApplGetParms function uses the following argument:
Argument
Type
Description
ParmValue
String
See Also
ApplGetParmValue Function, ApplSetParmValue Statement, CallApplic
Statement, CallApplicWait Statement
Example
The following code snippet illustrates how to call the Release Payroll Batch process to
release a particular Batch.
Dim ParmStr
As String
Reference
175
The following code snippet illustrates how the Release Payroll Batch process can
subsequently retrieve the parameters using the ApplGetParms statement from within
its Form1_Load event.
Dim Parm_Module
As String
Dim Parm_BatNbr
As String
Dim Parm_EditScrnNbr
As String
Dim Parm_Status
As String
Parm_Module = ApplGetParms()
Parm_BatNbr = ApplGetParms()
Parm_EditScrnNbr = ApplGetParms()
Parm_Status = ApplGetParms()
176
ApplGetParmValue Function
Description
Retrieve a parameter passed by another Tools for Visual Basic application.
Syntax
ParmValue = ApplGetParmValue(ParmSection, ParmName)
Remarks
Parameters passed to a Tools for Visual Basic application can be retrieved via one of
two different methods: ApplGetParms and ApplGetParmValue. These functions
differ in that ApplGetParms does not support multiple parameter sections whereas
ApplGetParmValue does provide this more sophisticated functionality. Consequently,
ApplGetParmValue is the only means by which the called application can retrieve
parameters from any named parameter section other than the default VBRDT section.
For example, if the calling application sends a parameter specifically designated as a
BSL parameter, only the ApplGetParmValue function can be used to retrieve that
particular parameter since the BSL section name can be explicitly queried via the
ParmSection argument.
Named parameter sections facilitate the elimination of conflicts which can occur in the
destination program when the application itself as well as custom BSL code added via
the Customization Manager are both attempting to receive different parameters. For
example, in Solomon the Accounts Payable Document Maintenance screen can
optionally receive two parameters that facilitate drill-down functionality: Reference
Number and Vendor ID. The Form_Load event always calls ApplGetParms once to
determine if any parameters have been passed to the application. If even one parameter
exists it is assumed that it is the Reference Number and therefore the application calls
ApplGetParms again expecting the next parameter to be the Vendor ID. If this screen
is subsequently customized by adding calls to ApplGetParms using BSL code, an
operational conflict will occur. If such an application were to be called with only one
parameter, designed to be received by the custom BSL code, it would instead be
received by the call to ApplGetParms performed by the underlying application.
Consequently the call to ApplGetParms in BSL code would not return any parameter
value at all.
ApplSetParmValue and ApplGetParmValue overcome this operational conflict by
facilitating the usage of named parameter sections. Using this more sophisticated
method, parameters can be passed directly to the application itself and to custom BSL
code using the two standard section names declared in applic.dh (e.g.,
PRMSECTION_VBRDT and PRMSECTION_BSL). Parameter sections are not,
however, limited to these two standard section names. Thus, for example, [XYZ
Section] is a valid section name. The brackets are required since parameter sections
themselves are handled similar to section names within an .INI file.
Reference
177
Type
Description
ParmValue
String
ParmSection
String
ParmName
String
See Also
ApplGetParms Function, ApplSetParmValue Statement, CallApplic Statement,
CallApplicWait Statement
Example
The following example will illustrate how to pass parameters to a Tools for Visual
Basic application and custom BSL code at the same time - and avoid conflicts between
the two.
Code in the calling application
Call ApplSetParmValue(PRMSECTION_VBRDT, "Batch Nbr", "000001")
Call ApplSetParmValue(PRMSECTION_VBRDT, "Document Nbr", "123456")
Call ApplSetParmValue(PRMSECTION_BSL, "Example Parm",
"Example Parameter To BSL Code")
'Call another VB RDT application
CallApplicWait( "RDTAPP", "")
178
As String
Dim Parm_DocumentNbr
As String
Basic Script code, overlaying the standard Tools for Visual Basic application, designed
to retrieve custom parameters:
Dim Parm_CustomParm As String
Parm_CustomParm = ApplGetParmValue(PRMSECTION_BSL, "Example Parm")
ApplGetReturnParms Function
Description
Retrieve a parameter returned from a now terminated secondary application.
Syntax
ParmValue = ApplGetReturnParms()
Remarks
If a Tools for Visual Basic application needs to pass parameters back to the program
from which it was originally called it can do so using one of the parameters to
ScreenExit. When control subsequently returns to the calling application, it can issue
one or more calls to ApplGetReturnParms to successively retrieve each individual
parameter.
The ApplGetReturnParms function has the following arguments:
Argument
Type
Description
ParmValue
String
See Also
ScreenExit Statement
Reference
ApplInit Statement
Description
Initialize various application resources as well as initiate a dynamic link with the
Solomon Parent.
Syntax
Call ApplInit
Remarks
This call is required in all applications developed with Tools for Visual Basic.
See Also
ScreenExit Statement, ScreenInit Statement
Example
The following code illustrates the basic order of calls that are made from within the
Form_Load event of Form1. Some of the calls are optional depending on the
requirements of a particular application but the ApplInit call is always required.
Sub Form_Load ()
'Load application sub-form(s)
'Call LoadForm( SubFormName)
'Call to Initialize the Application (required in all applications)
Call ApplInit
'SetAddr call(s)
'Call SetAddr(LEVEL0, "bTableName", bTableName, nTableName,
LenB(bTableName))
'SqlCursor call(s)
'Call SqlCursor(CSR_TableName, LEVEL0)
'Call to Initialize the Screen (required in all applications)
Call ScreenInit
'DetailSetup call for simple grid
'MemHandle_Spread1 = DetailSetup(CSR_TableName, Spread1_TableName,
PNULL, bTableName, LenB(bTableName), PNULL, 0, PNULL, 0, PNULL, 0)
End Sub
179
180
ApplSetFocus Statement
Description
Set focus to a designated control.
Syntax
Call ApplSetFocus( TargetCtrl)
Remarks
ApplSetFocus is the preferred method to explicitly set focus to a target control. Usage
of the Visual Basic .SetFocus method will cause a fatal VB error if the target control is
disabled or invisible. Developers must always remember that the design time property
setting of the target control cannot be guaranteed to always retain the same value at
runtime. For example, the target control may be both visible and enabled in the
standard application and therefore the .SetFocus will appear to work properly during
testing. However, the end user may subsequently apply a customization which among
other things disables the target control - thereby uncovering a subtle flaw in the
underlying application with regards to its usage of the .SetFocus method.
The ApplSetFocus statement uses the following arguments:
Argument
Type
Description
TargetCtrl
Control
Example
Call ApplSetFocus(Form1.cDiscBal)
Reference
181
ApplSetParmValue Statement
Description
Add one additional parameter to the list of all parameters which will be sent to the next
application called by either the CallApplic or CallApplicWait statement.
Syntax
Call ApplSetParmValue(ParmSection, ParmName, ParmValue)
Remarks
There are two different methods for one Tools for Visual Basic application to start
another application: CallApplic and CallApplicWait. Regardless of which statement
is used there are also two different methods for the calling program to pass parameters
to the called program.
The first method is to pass the parameters to the called program using the argument to
CallApplic and CallApplicWait specifically designed for this purpose. Parameters
passed via this method are all grouped together and passed directly to the called
application via the physical command line itself. Consequently, under this method the
size and/or number of parameters is limited to the maximum command line length less
the number of bytes used by Solomon for internal requirements, which can vary based
on the situation.
A more robust method of passing parameters is to use the ApplSetParmValue
statement in conjunction with either the CallApplic or CallApplicWait statement. The
principle advantage of using this method is that it allows the calling application to
group parameters into named sections and explicitly label individual parameters using
unique parameter names. Grouping parameters into named sections eliminates conflicts
that will occur in the called program when the application itself as well as custom BSL
code added via the Customization Manager are both attempting to receive different
parameters. See the ApplGetParmValue function for a more detailed explanation of
these potential conflicts.
The first call to ApplSetParmValue will create a temporary destination parameter file
and place the first parameter in that file. By default, this temporary file will be created
in the WINDOWS directory. This default can be overridden using the TempDirectory
entry in the [Miscellaneous] section of the SOLOMON.INI file. Following is an
example of the C:\TEMP directory specified as the parameter file directory in
SOLOMON.INI:
[Miscellaneous]
TempDirectory=C:\TEMP
182
Type
Description
ParmSection
String
ParmName
String
ParmValue
String
See Also
ApplGetParms Function, ApplGetParmValue Function, CallApplic Statement,
CallApplicWait Statement
Example
The following example will illustrate two different methods of calling ROI to display
the Vendor List report on the screen for all Vendors having a balance greater than zero.
Pass parameters to ROI via one large parameter argument to CallApplicWait. This
method will not work with a large WHERE clause since the entire contents of ParmStr
must fit on the physical command line.
Dim ParmStr
As String
Reference
183
184
AutoNbrDefault Function
Description
Set up auto-numbering.
Syntax
RetVal = AutoNbrDefault(Ctrl1, SqlProcName, Ctrl2, Ctrl3)
Remarks
This call will set up the ability for a specified SAFMaskedText control representing a
unique and sequentially numbered key field to be defaulted from a last number used
field in a setup record whenever a new record is saved.
This call needs to be placed in Form_Load in a very specific location relative to the
other calls. See the example for placement.
The application program must specify the keyfield control that will be defaulted with
the uniquely numbered string value and must also specify the stored procedure that will
retrieve the correct default information from a setup record within the database. The
stored procedure should retrieve two fields of information from the setup record:
The auto number flag associated with the field. This value must be a two byte
integer having a value of 0 if auto-numbering is turned off and 1 if autonumbering is turned on.
The last number used field. This must be a string field exactly ten bytes in
length. The value of this string field can be less then ten bytes but the field itself
must be exactly ten bytes.
Type
Description
RetVal
Integer
Ctrl1
Control
SqlProcName
String
Ctrl2
Control
Reference
Argument
Type
Description
Ctrl3
Control
185
Example
The following code snippet illustrates how automatic Batch numbering is implemented
in the Payroll Manual Check screen.
Sub Form_Load ()
Call ApplInit
Call SetAddr(LEVEL0, "bBatch", bBatch, nBatch, LenB(bBatch))
Call SetAddr(LEVEL1, "bPRDoc", bPRDoc, nPRDoc, LenB(bPRDoc))
Call SetAddr(LEVEL2, "bEmployee", bEmployee, nEmployee, LenB(bEmployee))
Call SetAddr(LEVEL3, "bPRTran1", bPRTran_Earn, nPRTran_Earn,
LenB(bPRTran_Earn))
Call SetAddr(LEVEL4, "bPRTran2", bPRTran_Ded, nPRTran_Ded,
LenB(bPRTran_Ded))
'Miscellaneous SetAddr calls
Call SetAddr(NOLEVEL, "bCASetup", bCASetup, nCASetup, LenB(bCASetup))
Call SetAddr(NOLEVEL, "bCashAcct", bCashAcct, nCashAcct,
LenB(bCashAcct))
Call SetAddr(NOLEVEL, "bDeduction", bDeduction, nDeduction,
LenB(bDeduction))
Call SetAddr(NOLEVEL, "bEarnType", bEarnType, nEarnType,
LenB(bEarnType))
Call SetAddr(NOLEVEL, "bPayGroup", bPayGroup, nPayGroup,
LenB(bPayGroup))
Call SetAddr(NOLEVEL, "bPayPeriod", bPayPeriod, nPayPeriod,
LenB(bPayPeriod))
Call SetAddr(NOLEVEL, "bPRSetup", bPRSetup, nPRSetup, LenB(bPRSetup))
'Setaddr calls for controls whose fieldname is not a database field
Call SetAddr(NOLEVEL, "bBatchHandling", bBatchHandling, PNULL,
LenB(bBatchHandling))
Call SetAddr(NOLEVEL, "bTempTotals", bTempTotals, PNULL,
LenB(bTempTotals))
'Initialize all cursors used by this screen.
Call Cursor_Init
186
' which need this record for default settings will have the values
' available when ScreenInit performs an implied NEW.
serr1 = SqlFetch1(CSR_PRSetup, "PRSetup_All", bPRSetup, LenB(bPRSetup))
Call ScreenInit
'Setup for auto batch numbering.
Note:
End Sub
Reference
187
Button_Form_Change Statement
Description
Allows an application to set the form change information triggered by a button click
event.
Syntax
Sub Button_Form_Change (ButtonName, Level, FromForm, ToForm)
Remarks
This statement will pass information needed for Transaction Import to automatically
generate button press statements in the control file. This call can be placed at the end of
FormLoad.
The Button_Form_Change statement uses the following arguments:
Argument
Type
Description
ButtonName
String
Level
Integer
FromForm
Integer
ToForm
Integer
See Also
Button_Level_Change statement.
188
Button_Level_Change Statement
Description
Allows an application to set the level change information triggered by a button click
event.
Syntax
Sub Button_Level_Change (ButtonName, FromLevel, ToLevel)
Remarks
This statement will pass information needed for Transaction Import to automatically
generate button press statements in the control file. This call can be placed at the end of
FormLoad.
The Button_Level_Change statement uses the following arguments:
Argument
Type
Description
ButtonName
String
FromLevel
Integer
ToLevel
Integer
See Also
Button_Form_Change statement.
Reference
189
CallApplic Statement
Description
Run another application.
Syntax
Call CallApplic(ApplicName, ParmStr)
Remarks
This statement allows the application to call, and optionally pass parameters to, another
application. Parameters passed via this method are all grouped together and passed
directly to the called application via the physical command line itself. A more robust
method of passing parameters is available in conjunction with the ApplSetParmValue
statement.
The called application can subsequently retrieve the parameters via one of two
different methods: ApplGetParms and ApplGetParmValue.
The called application will NOT be modal when the CallApplic statement is used. If
the called application is required to be modal then the CallApplicWait statement
should be utilized.
The CallApplic statement uses the following arguments:
Argument
Type
Description
ApplicName
String
ParmStr
String
See Also
ApplGetParms Function, ApplGetParmValue Function, ApplSetParmValue
Statement, CallApplicWait Statement
Example
The following simple line of code illustrates how the current application can call a
program named PROGRAMB with two parameters.
Call CallApplic("PROGRAMB", "Parm1" + PRMSEP + "Parm2")
190
CallApplicWait Statement
Description
Run another program as a modal application.
Syntax
Call CallApplicWait(ApplicName, ParmStr)
Remarks
This statement allows the application to call, and optionally pass parameters to, another
application. Parameters passed via this method are all grouped together and passed
directly to the called application via the physical command line itself. A more robust
method of passing parameters is available in conjunction with the ApplSetParmValue
statement.
The called application can subsequently retrieve the parameters via one of two
different methods: ApplGetParms and ApplGetParmValue.
The called application will be modal when the CallApplicWait statement is used. If
the called application should NOT be modal then the CallApplic statement should be
utilized.
The CallApplicWait statement uses the following arguments:
Argument
Type
Description
ApplicName
String
ParmStr
String
See Also
ApplGetParms Function, ApplGetParmValue Function, ApplSetParmValue
Statement, CallApplic Statement
Example
The following code snippet illustrates how to call the Release Payroll Batch process to
release a particular Batch.
Dim ParmStr
As String
Reference
191
CallChks Statement
Description
Perform error checking for the specified fields.
Syntax
ErrRet = CallChks( Form, BeginControl, EndControl, CallApplicChkEvent,
ChkDetailFields)
Remarks
This statement allows the application to perform error checking on a range of controls.
By default, error checking will not occur on a control unless it has been changed since
the last fetch. You can force error checks to occur regardless of whether the field
changed or not by setting parameter CallApplicChk to True. Controls on Detail levels
will be skipped unless parameter ChkDetailFields is True. Error checks will be
performed on each control in the range, but checking will terminate when an error
status is indicated on one of the controls. If all controls pass error checking, 0 is
returned. Otherwise non-zero is returned.
The CallCks statement uses the following arguments:
Argument
Type
Description
Form
Control
BeginControl
Control
EndControl
Control
CallApplicChk
Integer
ChkDetailFields
Integer
Return Value
Integer
See Also
ApplGetParms Function, ApplGetParmValue Function, ApplSetParmValue
Statement, CallApplic Statement
Example
MyErrVal=CallChks(Form1, cbatch, crefnbr, True, False)
192
ChkCuryRateType Function
Description
Standard routine for checking the validity of a Rate Type value. Checks whether a
RateType record exists for the desired Rate Type value. If a RateType record is not
found, the routine returns the database error code. A return value of 0 indicates
success.
Syntax
IntVar = ChkCuryRateType(bRateType)
Remarks
ChkCuryRateType is typically called by the application to check the validity of a
Vendors or Customers default Rate Type, before copying it to the Currency Selection
Form. Since the same logic was required in a number of applications, it was provided
as a standard routine, to minimize the amount of currency code in the applications.
The ChkCuryRateType statement uses the following arguments:
Argument
Type
Description
IntVar
Integer
bRateType
String
Example
The following example shows a portion of the Vendor Chk event for an application
being enabled for multi-currency processing.
Sub cvendid_Chk (chkstrg As String, retval As Integer)
Dim maintflg As Integer
'Fetch vendor record to display Name, status and Terms
retval = pvchkfetch1(cvendid, C3, chkstrg, bVendor, LenB(bVendor))
'Currency Manager
If retval = 0 Then
'If multi-currency entry is activated...
If bCMSetup.MCActivated = LTRUE Then
'If Vendor Currency ID is specified, and
'is different from Batch Currency ID...
Reference
193
Then
'Check whether Vendor Rate Type exists
serr1 = ChkCuryRateType(bVendor.CuryRateType)
If serr1 <> 0 Then
'If not, exit with error
retval = 6092
Exit Sub
Else
'If it does, try to retrieve Rate Table entry
Call CuryRateTypeSet(bVendor.CuryRateType)
Call GetCuryRate
End If
End If
End If
End If
End If
End Sub
194
CurrencyField Statement
Description
Identifies Transaction Currency Controls and their corresponding Base Currency fields.
The Flags parameter specifies whether or not the Base Currency field value should be
recalculated before display. The information passed in the parameters is stored in the
task memory of the application, and is used whenever Currency Rate Information is
changed within the Currency Selection Form (opened from the Toolbar) or the
Currency View is changed by pressing the Currency View button on the Toolbar.
Syntax
Call CurrencyField(hctlTranCuryFld, bBaseCuryFld, Flags)
Remarks
Add a CurrencyField call to the Form_Load event for each application control which
you wish to give automatic currency calculation and display capabilities. This typically
includes all controls used to enter a monetary value. The parameter information is
saved by SWIM and used to redisplay monetary values when the user changes
Currency Rate Information within the Currency Selection Form or toggles between
the Transaction Currency Amounts and Base Currency Amounts, using the Currency
View button.
Note: The FieldName property of the monetary control should typically be set to the
database field which will hold the Transaction Currency value in the database. In
Solomon record structures, the Transaction Currency field typically has a Cury
prefix. For example, in APTran, the Transaction Currency transaction amount would
be stored in CuryTranAmt. The corresponding Base Currency amount is typically
stored in a similar field name without the Cury prefix. For example, in APTran, the
Base Currency transaction amount is stored in TranAmt. Since you will usually want
both the Transaction Currency amount and the Base Currency Amount stored in the
database, you will typically specify the control associated with the Transaction
Currency field as the first parameter in the CurrencyField call, and the location of the
Base Currency field as the second parameter in the CurrencyField call. However, it is
possible to use the handle of any SAFFloat control and the location of any Double
variable field as parameters.
You will usually want the Base Currency value to be automatically calculated or
recalculated when the user changes the Currency Rate Information in the Currency
Selection form and when the user toggles between Transaction Currency and Base
Currency views. (Whenever the Base Currency value is recalculated, Currency Rate
Information is also updated in the fields specified by CurrencyInfo for the Update
Level which contains the monetary field.) For the typical case, the Flags parameter
should be set to CURY_BASE_CALC.
Reference
195
There will be some cases when monetary fields are displayed for inquiry only, and you
will not want the Base Currency values changed in any way. In those cases the Flags
parameter should be set to CURY_BASE_NOCALC. The same application may need
to calculate Base Currency in some situations, but not others. For example, when you
retrieve an open document, you may want to be able to change monetary amounts and
recalculate Base Currency values, but when you retrieve a released document, you may
want to suppress changes. CuryFieldCalcSet is used to reset the Flags value during
execution.
CurrencyField calls should follow ScreenInit and DetailSetup calls. CurrencyField
calls should be executed, even if multi-currency processing is not enabled, to insure
that database fields are properly populated with Base Currency values.
The CurrencyField statement uses the following arguments:
Argument
Type
Description
hctlTranCuryFld
Control
bBaseCuryFld
Double
Flags
Integer
See Also
CurrencyInfo Statement, CuryFieldCalcSet Statement
Example
The following example shows a portion of the Form_Load event for an application
being enabled for multi-currency processing.
Call ApplInit
Call setaddr(LEVEL0, "bBatch", bBatch, nBatch, LenB(bBatch
Call setaddr(LEVEL1, "bAPDoc", bAPDoc, nAPDoc, LenB(bAPDoc))
Call setaddr(LEVEL2, "bAPTran", baptran, nAPTran, LenB(baptran))
Call setaddr(NOLEVEL, "bCuryInfo", bCuryInfo, nCuryInfo, LenB(bCuryInfo))
Call setaddr(NOLEVEL, "bCMSetup", bCMSetup, nCMSetup, LenB(bCMSetup))
Call SqlCursor(C1, LEVEL0) 'Batch
Call SqlCursor(C2, LEVEL1) 'APDoc
Call SqlCursor(C3, LEVEL2) 'APTran
'Set up Currency Info Fields for CM
'Note - these calls need to be made even if CM is not installed.
Call CurrencyInfo(LEVEL0, bBatch, "Batch", "CuryId", "CuryMultDiv",
"CuryRateType", bBatch.CuryEffDate, bBatch.CuryRate)
196
NULLDATE, bAPTran.CuryRate)
'Initialize and Enable Currency Manager Controls
serr1 = sqlfetch1(c7, "CMSetup_All", bCMSetup, LenB(bCMSetup))
'If Currency Manager is installed and Multi-Currency is activated ...
If serr1 = 0 And bCMSetup.MCActivated = LTRUE Then
'Activate Currency Buttons on Toolbar
Call SetButton(CurySelButton + CuryTogButton, AllLevels, True)
'Set default rate type
Call CuryRateTypeSet(bCMSetup.APRtTpDflt)
'If rate type override is not allowed,
'disable rate type field in Currency Selection form
If bCMSetup.APRtTpOverride = LFALSE Then
Call CurySelFieldEnable(CURYSEL_RATETYPE, False)
SaveCURYSEL_RATETYPE = CURYSEL_RATETYPE
Else
SaveCURYSEL_RATETYPE = 0
End If
End If
ScreenInit
'Voucher Detail Grid
mhandle = detailsetup(C3, Form1.Spread1, baptran.linenbr, baptran,
LenB(baptran), PNULL, 0, PNULL, 0, PNULL, 0)
'Set up Currency Fields for CM
'Note - these calls need to be made even if CM is not installed.
Call CurrencyField(Form1.cctrltot, bBatch.ctrltot, CURY_BASE_CALC)
Call CurrencyField(Form1.corigdocamt, bAPDoc.OrigDocAmt,
CURY_BASE_CALC)
Call CurrencyField(Form1.cdiscbal, bAPDoc.DiscBal, CURY_BASE_CALC)
Call CurrencyField(Form1.cdrtot, bBatch.DrTot, CURY_BASE_CALC)
Call CurrencyField(Form1.cdocbal, bAPDoc.DocBal, CURY_BASE_CALC)
Call CurrencyField(Form1.cunitprice, baptran.unitprice,
CURY_BASE_CALC)
Call CurrencyField(Form1.ctranamt, baptran.TranAmt, CURY_BASE_CALC)
Reference
197
CurrencyInfo Statement
Description
Saves the addresses of the application fields where Currency Rate Information will be
stored for each update level. Saving the addresses allows the Currency Rate
Information to be moved between the Currency Selection Form (opened from the
Toolbar) and the application records, using CuryInfoGet and CuryInfoSet calls.
Syntax
Call CurrencyInfo(Level, RecAddr, RecName, IDFldName, MDFldName,
RateTypeFldName, Effdate, Rate)
Remarks
Add a CurrencyInfo call to the Form_Load event for each Update Level which needs
to update the database with Currency Selection Information. Possible fields to be
updated are Currency ID, Multiply/Divide, Rate Type, Effective Date, and Rate. Some
record structures only store the Currency ID, Multiply/Divide, and Rate values. An
empty string and the NULLDATE constant are used as the values of the Rate Type and
Effective date parameters for record structures which do not store those fields.
CurrencyInfo calls should be done after SetAddr calls, which establish levels for
record structures, but before the ScreenInit call. CurrencyInfo calls should be
executed even when multi-currency processing is not enabled, to insure the Currency
Rate Information fields are correctly populated for Base Currency processing.
The CurrencyInfo statement uses the following arguments:
Argument
Type
Description
Level
Integer
RecAddr
Any
RecName
String
IDFldName
String
MDFldName
String
RateTypeFldName String
EffDate
Sdate
Rate
Double
198
See Also
CuryInfoGet Statement, CuryInfoInit Statement, CuryInfoSet Statement
Example
The following example shows a portion of the Form_Load event for an application
being enabled for multi-currency processing. Note that the Batch and APDoc records
in LEVEL0 and LEVEL1 contain all of the Currency Information fields, while the
APTran record in LEVEL3 only contains Currency ID, Multiply/Divide, and Rate.
Call
Call
Call
Call
Call
Call
Call
Call
Call
'Set
ApplInit
setaddr(LEVEL0, "bBatch", bBatch, nBatch, LenB(bBatch
setaddr(LEVEL1, "bAPDoc", bAPDoc, nAPDoc, LenB(bAPDoc))
setaddr(LEVEL2, "bAPTran", baptran, nAPTran, LenB(baptran))
setaddr(NOLEVEL, "bCuryInfo", bCuryInfo, nCuryInfo, LenB(bCuryInfo))
setaddr(NOLEVEL, "bCMSetup", bCMSetup, nCMSetup, LenB(bCMSetup))
SqlCursor(C1, LEVEL0) 'Batch
SqlCursor(C2, LEVEL1) 'APDoc
SqlCursor(C3, LEVEL2) 'APTran
up Currency Info Fields for CM
NULLDATE, bAPTran.CuryRate)
Reference
199
CuryEffDateSet Statement
Description
Sets the value of the Effective Date field in the Currency Selection Form (opened from
the Toolbar).
Syntax
Call CuryEffDateSet(bEffDate)
Remarks
This routine is typically called from the Chk events of the application date fields which
are potential defaults for the Effective Date in the Currency Selection Screen. Choice
of default Effective date is a Currency Manager Setup option.
Note: This routine does not automatically retrieve new rate information into the
Currency Selection Form. If new rate information is desired, this call must be followed
by a call to GetCuryRate.
The CuryEffDateSet statement uses the following arguments:
Argument
Type
Description
bEffDate
SDate
See Also
CuryIdSet Statement, CuryRateTypeSet Statement, GetCuryRate Statement
Example
The following example shows the Chk event for a Document Date field. If multicurrency entry is activated and the default Effective Date selected in Currency
Manager Setup is Document Date, the Effective Date in the Currency Selection
Form is set to the Document Date.
Sub cdocdate_Chk (chkstrg As String, retval As Integer)
Dim tempdate As sdate
'Currency Manager
If bCMSetup.MCActivated = LTRUE And bCMSetup.APRateDate = "D" Then
Call strtodate(chkstrg, tempdate)
If datecmp(tempdate, bCuryInfo.EffDate) <> 0 Then
Call CuryEffDateSet(chkstrg)
Call GetCuryRate
End If
End If
End Sub
200
CuryFieldCalcSet Statement
Description
Allows application to reset flag value which determines whether or not Base Currency
value associated with a control is recalculated prior to display. The flag value is stored
in the task memory of the application, and is used whenever Currency Rate
Information is changed within the Currency Selection Form (opened from the Toolbar)
or the Currency View is changed by pressing the Currency View button on the
Toolbar.
Syntax
Call CuryFieldCalcSet(hctlTranCuryFld, Flags)
Remarks
When CurrencyField calls are made in the Form_Load event, the information
contained in the CurrencyField parameters is stored in task memory for use in
automatically calculating Base Currency and toggling between Transaction Currency
and Base Currency values. The Flags parameter value sent by the CurrencyField call
indicates whether the Base Currency value should be recalculated prior to display, or
just displayed. If it is necessary to change the original Flags value, as the state of the
displayed Document or Batch is changed, CuryFieldCalcSet is used. To allow Base
Currency to be recalculated, Flags should be set to CURY_BASE_CALC. To suppress
recalculation of Base Currency, Flags should be set to CURY_BASE_NOCALC.
When calculation is suppressed, toggling to Base Currency still displays the value
previously calculated and stored in the Base Currency field.
The CuryFieldCalcSet statement uses the following arguments:
Argument
Type
Description
hctlTranCuryFld
Control
Flags
Integer
See Also
CurrencyField Statement
Reference
201
Example
The following example shows a portion of the Chk event for a Document Reference
number. If the Document has been released, no changes are allowed to Document
amounts. Consequently, as an Safeguard, the code also suppresses automatic
recalculation of Base Currency amounts. Please note that for an open document,
CuryFieldCalcSet calls are made to insure that Base Currency calculation is reenabled, in case it had been disabled for the previously retrieved document. This logic
assumes that CurrencyField calls have been made in the Form_Load event for each
control for which a CuryFieldCalcSet call is made here.
Sub crefnbrh_Chk (chkstrg As String, retval As Integer)
retval = NoAutoChk
serr1 = pvchkfetch1(PNULL, C2, chkstrg, bAPDoc, LenB(bAPDoc))
If serr1 = 0 Then
'Currency Manager
If bCMSetup.MCActivated = LTRUE Then
'If batch has already been released, all Currency
'Selection fields should have been disabled when
'batch was retrieved, so do nothing here.
If bBatch.Rlsed = LFALSE Then
'If batch has not been released, but document
'has, disable all Currency Selection fields.
If bAPDoc.Rlsed = LTRUE Then
Call CurySelFieldEnable(CURYSEL_ALL, False)
Call CuryFieldCalcSet(Form1.corigdocamt, CURY_BASE_NOCALC)
Call CuryFieldCalcSet(Form1.cdiscbal, CURY_BASE_NOCALC)
Call CuryFieldCalcSet(Form1.cdocbal, CURY_BASE_NOCALC)
Call CuryFieldCalcSet(Form1.cunitprice, CURY_BASE_NOCALC)
Call CuryFieldCalcSet(Form1.ctranamt, CURY_BASE_NOCALC)
Call CuryInfoEnable(LEVEL1, CURY_INFO_SETONLY)
Call CuryInfoEnable(LEVEL4, CURY_INFO_SETONLY)
'Otherwise disable Tran Currency ID to disallow
'changing currency in existing document.
Else
Call CurySelFieldEnable(CURYSEL_ALL, True)
Call CurySelFieldEnable(CURYSEL_TRANCURYID +
SaveCURYSEL_RATETYPE, False)
202
(Under normal
Reference
203
CuryInfoEnable Statement
Description
Allows application to enable or disable CuryInfoGet and CuryInfoSet calls.
Syntax
Call CuryInfoEnable(Level, Flag)
Remarks
CuryInfoGet calls are used to copy Currency Rate Information values from the
Currency Selection Form (opened from the Toolbar) to previously-specified fields in
the database record structure used for a particular update level in the application.
CuryInfoSet calls are used to copy Currency Rate Information field values from the
database record structure for a particular update level into the Currency Selection
Form. The database record structure fields which will hold the Currency Rate
Information are specified by CurrencyInfo calls in the Form_Load event.
CuryInfoGet and CuryInfoSet calls are typically made in several different places
within the application. They are also called internally from SWIM as part of other
SWIM routines. If no CuryInfoEnable calls are made, the default mode will enable
both CuryInfoGet and CuryInfoSet actions. When the Batch, Document, and
Transaction are in certain processing states, it may be desirable to suppress the copying
of Currency Rate Information to and/or from the Currency Selection Form for one or
more update levels. It would be inconvenient to use conditional logic around every
CuryInfoGet and/or CuryInfoSet call made in the application, and even more
difficult to conditionally execute the calls made within SWIM. Instead,
CuryInfoEnable is used to tell SWIM to ignore CuryInfoGet, CuryInfoSet, or both.
CuryInfoEnable is also used to re-enable processing of CuryInfoGet, CuryInfoSet,
or both.
The CuryInfoEnable statement uses the following arguments:
Argument
Type
Description
Level
Integer
Flag
Integer
See Also
CuryInfoGet Statement, CuryInfoSet Statement, CurrencyInfo Statement
204
Example
The following example shows a portion of the Chk event for a Document Reference
number. If the Document has been released, no changes are allowed to Document
amounts. Consequently, as an Safe guard, the retrieval of Currency Rate Information
into the Document from the Currency Selection screen, using CuryInfoGet, is also
suppressed for the Document and Detail levels. Please note that CuryInfoSet calls are
still allowed, since they are necessary in order to allow the Currency Selection Form to
display the Currency Rate Information previously stored in the Document. For an open
document, CuryInfoEnable calls are made to insure that CuryInfoSet and
CuryInfoGet are re-enabled, in case they had been disabled for the previouslyretrieved Document.
Sub crefnbrh_Chk (chkstrg As String, retval As Integer)
retval = NoAutoChk
serr1 = pvchkfetch1(PNULL, C2, chkstrg, bAPDoc, LenB(bAPDoc))
If serr1 = 0 Then
'Currency Manager
If bCMSetup.MCActivated = LTRUE Then
'If batch has already been released, all Currency
'Selection fields should have been disabled when
'batch was retrieved, so do nothing here.
If bBatch.Rlsed = LFALSE Then
'If batch has not been released, but document
'has, disable all Currency Selection fields.
If bAPDoc.Rlsed = LTRUE Then
Call CurySelFieldEnable(CURYSEL_ALL, False)
Call CuryFieldCalcSet(Form1.corigdocamt, CURY_BASE_NOCALC)
Call CuryFieldCalcSet(Form1.cdiscbal, CURY_BASE_NOCALC)
Call CuryFieldCalcSet(Form1.cdocbal, CURY_BASE_NOCALC)
Call CuryFieldCalcSet(Form1.cunitprice, CURY_BASE_NOCALC)
Call CuryFieldCalcSet(Form1.ctranamt, CURY_BASE_NOCALC)
Call CuryInfoEnable(LEVEL1, CURY_INFO_SETONLY)
Call CuryInfoEnable(LEVEL4, CURY_INFO_SETONLY)
Reference
205
(Under normal
206
CuryInfoGet Statement
Description
Moves Currency Rate Information from the Currency Selection Form (opened from the
Toolbar) to the application database record where Currency Rate Information will be
stored for a particular update level. In order to use CuryInfoGet for a particular update
level, a CurrencyInfo call must have been made in Form_Load for the update level.
Syntax
Call CuryInfoGet(Level)
Remarks
CuryInfoGet calls are used to retrieve Currency Rate Information values previously
defaulted into or entered into the Currency Selection Form (opened from the Toolbar)
and copy the values to the Currency Rate Information fields in the database record
structure used for a particular update level in the application. CuryInfoGet assumes
that a CurrencyInfo call was done in the Form_Load event for each Update Level
which needs to update the database with Currency Selection Information. Locations
saved by the CurrencyInfo call are used by CuryInfoGet to determine where to store
the retrieved values.
CuryInfoGet calls for Batch and Document levels are typically done within the
Update_New event of the application. CuryInfoGet calls for detail levels are typically
done within the logic for initializing a new detail line in the LineGotFocus event for
the spreadsheet.
The CuryInfoGet statement uses the following arguments:
Argument
Type
Description
Level
Integer
See Also
CuryInfoInit Statement, CuryInfoSet Statement, CurrencyInfo Statement
Example
The first example below shows a portion of the Update_New event for an application
being enabled for multi-currency processing. CuryInfoGet calls for the Batch and
Document levels are done here. Note that one of the CuryInfoGet calls is actually
made within a subroutine called Init_Enable_Batch_Currency, which performs a group
of operations required for Currency initialization at the Batch level. The call to the
subroutine is made within the Level 0 case logic, and the subroutine is shown
following the Update_NewLevel event code segment.
Reference
Sub Update1_NewLevel (level%, retval%)
'Set Un-Entered fields for batch and document levels
Select Case level
Case 0
'Batch
bBatch.GLPostOpt = bAPSetup.GLPostOpt
bBatch.PerEnt = bAPSetup.CurrPerNbr
bBatch.JrnlType = "AP"
bBatch.Module = "AP"
bBatch.EditScrnNbr = "03010"
bBatch.Status = "H"
bBatch.BatType = "N"
bBatchHandling.BatchHandling = "H"
'Initialize and Enable Currency Manager fields
If bCMSetup.MCActivated = LTRUE Then
Call Init_Enable_Batch_Currency
Else
Call CuryInfoGet(LEVEL0)
End If
Case 1
'Document
bAPDoc.PerEnt = bAPSetup.CurrPerNbr
bAPDoc.DocClass = "N"
bAPDoc.Selected = LFALSE
bAPDoc.Current = LTRUE
bAPDoc.OpenDoc = LTRUE
SaveBal = LTRUE
'Currency Manager
Call CuryInfoGet(LEVEL1)
End Select
End Sub
207
208
The second example below shows the Spread1_LineGotFocus event for an application
being enabled for multi-currency processing. The CuryInfoGet call for the Detail level
is done here.
Sub Spread1_LineGotFocus (maintflg%, retval%)
If maintflg = NEWROW Then
Reference
baptran.JrnlType = "AP"
baptran.RefNbr = bAPDoc.RefNbr
baptran.PerEnt = bAPDoc.PerEnt
baptran.Rlsed = LFALSE
baptran.AcctDist = LFALSE
'Determine the Entry Type
If bAPDoc.DocType = "VO" Or bAPDoc.DocType = "AC" Then
baptran.DrCr = "D"
'Debit
baptran.DrCr = "C"
'Credit
Else
End If
'Currency Manager - Set detail currency info fields
'to CURYSEL values.
Call CuryInfoGet(LEVEL2)
End If
End Sub
209
210
CuryInfoInit Statement
Description
Initializes Currency Rate Information in the Currency Selection Form (opened from the
Toolbar) to Base Currency values. Transaction Currency ID is set to the Base Currency
ID for the database. Rate Type is set to blanks. Effective Date is set to the current
business date. Multiply/Divide is set to M. Rate is set to 1.0. Also sets the Currency
View button image to the image associated with Base Currency.
Syntax
Call CuryInfoInit
Remarks
CuryInfoInit calls are used to reinitialize the Currency Rate Information values in the
Currency Selection form to Base Currency values. When an application is called from
the Solomon Applications menu, the Currency Selection form is automatically
initialized with Base Currency values, so it isnt necessary for the application to
initialize the values when execution begins. However, the application will typically
need to re-initialize Currency Rate Information as part of the New logic for the
LEVEL0 Batch or Document. If it is possible to initiate a new Batch or Document
from the Batch Number or Reference Number Chk event, CuryInfoInit may also need
to be executed there.
The CuryInfoInit statement does not require any arguments.
See Also
CuryInfoGet Statement, CuryInfoSet Statement
Example
The following example shows a portion of the Update_NewLevel LEVEL0 case logic
for an application being enabled for multi-currency processing. Note that CuryInfoInit
is actually called within the subroutine Init_Enable_Batch_Currency, which is used to
group currency initialization logic for the Batch level, and is shown following the
Update_NewLevel code segment.
Sub Update1_NewLevel (level%, retval%)
'Set Un-Entered fields for batch and document levels
Select Case level
Case 0
'Batch
Reference
211
bBatch.GLPostOpt = bAPSetup.GLPostOpt
bBatch.PerEnt = bAPSetup.CurrPerNbr
bBatch.JrnlType = "AP"
bBatch.Module = "AP"
bBatch.EditScrnNbr = "03010"
bBatch.Status = "H"
bBatch.BatType = "N"
bBatchHandling.BatchHandling = "H"
'Initialize and Enable Currency Manager fields
If bCMSetup.MCActivated = LTRUE Then
Call Init_Enable_Batch_Currency
Else
Call CuryInfoGet(LEVEL0)
End If
Sub Init_Enable_Batch_Currency ()
Call CuryFieldCalcSet(Form1.cctrltot, CURY_BASE_CALC)
Call CuryFieldCalcSet(Form1.corigdocamt, CURY_BASE_CALC)
Call CuryFieldCalcSet(Form1.cdiscbal, CURY_BASE_CALC)
Call CuryFieldCalcSet(Form1.cdrtot, CURY_BASE_CALC)
Call CuryFieldCalcSet(Form1.cdocbal, CURY_BASE_CALC)
Call CuryFieldCalcSet(Form1.cunitprice, CURY_BASE_CALC)
Call CuryFieldCalcSet(Form1.ctranamt, CURY_BASE_CALC)
Call CuryInfoInit
Call CuryRateTypeSet(bCMSetup.APRtTpDflt)
Call CuryInfoGet(LEVEL0)
Call CurySelFieldEnable(CURYSEL_ALL, True)
Call CurySelFieldEnable(SaveCURYSEL_RATETYPE, False)
End Sub
The following example below shows the Batch Number Chk event for an application
being enabled for multi-currency processing. Note that CuryInfoInit is actually called
within the subroutine Init_Enable_Batch_Currency, which is shown above.
212
Reference
End If
'If Currency values were previously saved in batch
'display them in Currency Selection form.
(Under normal
213
214
CuryIdSet Statement
Description
Sets the value of the Transaction Currency ID field in the Currency Selection Form
(opened from the Toolbar). Also sets the Currency View button image to the image
associated with the new Transaction Currency ID.
Syntax
Call CuryIdSet(bCuryId)
Remarks
CuryIdSet is used in some non-standard applications to set the Transaction Currency
ID and Currency View button image without entering the Currency Selection form.
Note: This routine does not automatically retrieve new rate information into the
Currency Selection Form. If new rate information is desired, this call must be followed
by a call to GetCuryRate.
The CuryIdSet statement uses the following arguments:
Argument
Type
Description
bCuryId
String
See Also
CuryRateTypeSet Statement, CuryEffDateSet Statement, GetCuryRate
Statement
Example
The following example below shows the Spread1_LineGotFocus event for an
application which changes the image on the Currency View button to show the image
corresponding to the Currency ID of the Account represented by each detail line.
Sub Spread1_LineGotFocus (maintflg%, retval%)
'Currency Manager - Set detail currency info fields
'to CURYSEL values.
Call CuryIDSet(bCashAcct.curyid)
End Sub
Reference
215
CuryInfoSet Statement
Description
Moves Currency Rate Information from the application database record where
Currency Rate Information has been stored for a particular update level to the Currency
Selection Form (opened from the Toolbar). Also updates the Currency View button
image. In order to use CuryInfoSet for a particular update level, a CurrencyInfo call
must have been made in Form_Load for the update level.
Syntax
Call CuryInfoSet(Level)
Remarks
CuryInfoSet calls are used to retrieve Currency Rate Information values from the
database record structure used for a particular update level in the application and copy
the values to the Currency Rate Information fields in the Currency Selection Form
(opened from the Toolbar). CuryInfoSet assumes that a CurrencyInfo call was done
in the Form_Load event for each Update Level which contains Currency Selection
Information. Locations saved by the CurrencyInfo call are used by CuryInfoSet to
determine where to find the Currency Rate Information values in the database record
structure.
CuryInfoSet calls for Batch and Document levels are typically done within the Batch
Number and Document Reference Number Chk events of the application. When an
existing Batch or Document is retrieved, the Currency Selection Form is updated to
show the Currency Rate Information previously saved in the database record structure.
The Currency View button image is also updated to show the image corresponding to
the Batch or Document Currency ID.
Note: It is a Microsoft Business Solutions convention that all Documents within the
same Batch must have the same Currency ID. However, different Documents within
the same Batch may have different Rate Types, Effective Dates, Rates, and
Multiply/Divide operators. Transactions within a Document must have the same
Currency Rate Information as the Document.
In a typical data entry screen, where detail lines represent Transaction records within a
Document, it is not necessary to call CuryInfoSet for each detail line, because all
Transactions have the same Currency Rate Information values as the Document with
which they are associated. However, if each detail line represents a Document or
Batch, a CuryInfoSet call may need to be done for each detail line as it gains focus, so
that the Currency Selection Form will show the information from the focused detail. In
that case, CuryInfoSet should be called within the logic for displaying existing detail
lines in the Spread1_LineGotFocus event, and within any detail control Chk event
which could cause the Currency Rate Information to change.
216
Type
Description
Level
Integer
See Also
CuryInfoGet Statement, CuryInfoInit Statement, CurrencyInfo Statement
Example
The following example below shows a portion of the Batch Chk event for an
application being enabled for multi-currency processing.
Sub cbatnbrb_Chk (chkstrg As String, retval As Integer)
retval = NoAutoChk
serr1 = pvchkfetch1(PNULL, c1, chkstrg, bBatch, LenB(bBatch))
If serr1 = 0 Then
'Multi-Currency Activated
If bCMSetup.MCActivated = LTRUE Then
'If batch has already been released,
'disable all Currency Selection fields.
'Also disable Base Currency Calculations
'in all fields that were originally calced.
If bBatch.Rlsed = LTRUE Then
Call CurySelFieldEnable(CURYSEL_ALL, False)
Call CuryFieldCalcSet(Form1.cctrltot, CURY_BASE_NOCALC)
Call CuryFieldCalcSet(Form1.corigdocamt, CURY_BASE_NOCALC)
Call CuryFieldCalcSet(Form1.cdiscbal, CURY_BASE_NOCALC)
Call CuryFieldCalcSet(Form1.cdrtot, CURY_BASE_NOCALC)
Call CuryFieldCalcSet(Form1.cdocbal, CURY_BASE_NOCALC)
Call CuryFieldCalcSet(Form1.cunitprice, CURY_BASE_NOCALC)
Call CuryFieldCalcSet(Form1.ctranamt, CURY_BASE_NOCALC)
Call CuryInfoEnable(LEVEL0, CURY_INFO_SETONLY)
Call CuryInfoEnable(LEVEL1, CURY_INFO_SETONLY)
Call CuryInfoEnable(LEVEL4, CURY_INFO_SETONLY)
'Otherwise disable Tran Currency ID to disallow
'changing currency in existing batch.
Else
Call CurySelFieldEnable(CURYSEL_ALL, True)
Reference
217
Call CurySelFieldEnable(CURYSEL_TRANCURYID +
SaveCURYSEL_RATETYPE, False)
Call CuryFieldCalcSet(Form1.cctrltot, CURY_BASE_CALC)
Call CuryFieldCalcSet(Form1.corigdocamt, CURY_BASE_CALC)
Call CuryFieldCalcSet(Form1.cdiscbal, CURY_BASE_CALC)
Call CuryFieldCalcSet(Form1.cdrtot, CURY_BASE_CALC)
Call CuryFieldCalcSet(Form1.cdocbal, CURY_BASE_CALC)
Call CuryFieldCalcSet(Form1.cunitprice, CURY_BASE_CALC)
Call CuryFieldCalcSet(Form1.ctranamt, CURY_BASE_CALC)
Call CuryInfoEnable(LEVEL0, CURY_INFO_SETGET)
Call CuryInfoEnable(LEVEL1, CURY_INFO_SETGET)
Call CuryInfoEnable(LEVEL4, CURY_INFO_SETGET)
End If
'If Currency values were previously saved in batch
'display them in Currency Selection form.
(Under normal
218
CuryRateTypeSet Statement
Description
Sets the value of the Rate Type field in the Currency Selection Form (opened from
toolbar).
Syntax
Call CuryRateTypeSet(bRateType)
Remarks
Since the default rate type varies by module, the application typically uses
CuryRateTypeSet to set the default rate type to be initially shown in the Currency
Selection Form. CuryRateTypeSet may also be called from the Vendor or Customer
Chk event to set the rate type to the default for the Vendor or Customer.
Note: This routine does not automatically retrieve new rate information into the
Currency Selection Form. If new rate information is desired, this call must be followed
by a call to GetCuryRate.
The CuryRateTypeSet statement uses the following arguments:
Argument
Type
Description
bRateType
String
See Also
CuryIdSet Statement, CuryEffDateSet Statement, GetCuryRate Statement
Example
The following example shows a portion of the Form_Load event for an application
being enabled for multi-currency processing. Note that CuryRateTypeSet is called to
set the rate type in the Currency Selection Screen to the default rate type for AP data
entry, stored in the Setup record.
Call ApplInit
Call setaddr(LEVEL0, "bBatch", bBatch, nBatch, LenB(bBatch
Call setaddr(LEVEL1, "bAPDoc", bAPDoc, nAPDoc, LenB(bAPDoc))
Call setaddr(LEVEL2, "bAPTran", baptran, nAPTran, LenB(baptran))
Call setaddr(NOLEVEL, "bCuryInfo", bCuryInfo, nCuryInfo, LenB(bCuryInfo))
Call setaddr(NOLEVEL, "bCMSetup", bCMSetup, nCMSetup, LenB(bCMSetup))
Call SqlCursor(C1, LEVEL0) 'Batch
Call SqlCursor(C2, LEVEL1) 'APDoc
Call SqlCursor(C3, LEVEL2) 'APTran
Reference
219
220
CurySelFieldEnable Statement
Description
Allows the application to control the enabling and disabling of fields within the
Currency Selection Form, opened from the Toolbar.
Syntax
Call CurySelFieldEnable(FieldId, Enabled)
Remarks
CurySelFieldEnable allows the application to set the state of data entry in the
Currency Selection Form to be consistent with the data entry state of the application.
The fields (field groups) which can be enabled or disabled by the application are
Currency ID, Rate Type, and All. The starting state for the typical application is that all
Currency Selection Form fields are enabled. A CurySelFieldEnable call is typically
made, along with other initialization logic, in the LEVEL0 case of the
Update_NewLevel event to enable all fields in the Currency Selection Form. By
Microsoft Business Solutions convention, all documents within a Batch must have the
same Currency ID. Consequently, once the first Document of the Batch has been
saved, the application may do a CurySelFieldEnable call to disable entry into the
Currency ID field of the Currency Selection Form. Override of the Rate Type field in the
Currency Selection Form is a Setup option. The application would typically retrieve
the Setup record, and then make a CurySelFieldEnable call to disable entry into the
Rate Type field, if necessary. If a Document is retrieved for inquiry only, the
application would make a CurySelFieldEnable call to disable all Currency Selection
Form fields. When creating or retrieving a new Document, the application would
typically call CurySelFieldEnable to re-initialize Currency Selection Form entry for
the next operation.
Note: It may be necessary to undo changes made for the state of the previous
Document.
Some operations are done using two or more consecutive CurySelFieldEnable calls.
For example, the logic for starting a new Document would need to undo any possible
previous field-disabling operations made during entry of the previous Document, and
then set a rate type restriction, if necessary. This would be done by first making a
CurySelFieldEnable call to enable All, and then making a second
CurySelFieldEnable call to disable only the Rate Type field. (The effects of
consecutive calls are cumulative.)
Reference
221
The Currency Selection Form itself has field enabling and disabling logic which is
designed to work in conjunction with the application. Upon initial entry into a screen,
the values of all of the Currency Selection Form fields are automatically set to Base
Currency values. As long as the Transaction Currency ID value is the same as Base
Currency, no other fields in the Currency Selection Form may be changed. When the
Transaction Currency and the Base Currency are the same, it is important that the
SWIM currency conversion routines use a Rate of 1.0, so no changes are allowed,
unless the user first changes the Transaction Currency ID. Unless the application has
made a CurySelFieldEnable call which disables the Transaction Currency ID field, the
user will be able to change the Transaction Currency ID field value from the Base
Currency value to another Currency ID value. Entry to the other fields on the screen
will then be enabled, unless the application has made a CurySelFieldEnable call
which causes one or more of them to remain disabled. For example, if the application
has made a CurySelFieldEnable call to disable Rate Type, the other fields will become
enabled, but Rate Type will remain disabled.
The CurySelFieldEnable statement uses the following arguments:
Argument
Type
Description
FieldIDs
Integer
EnableFlag
Integer
Example
The following example shows the Batch Chk event for an application being enabled for
multi-currency processing. Note that if the Batch has already been released, all
Currency Selection Form fields are disabled. If the Batch has not been released, all
Currency Selection Form fields are enabled, except for Transaction Currency ID and
possibly Rate Type. Transaction Currency ID is disabled, because by Microsoft Business
Solutions convention, the user is not allowed to change the currency of an existing
batch. Rate Type may or may not be disabled, depending upon the value of
saveCURYSEL_RATETYPE, which was previously set to CURYSEL_RATETYPE or
0 in the Form_Load event (not shown), depending upon the value of the Rate Type
override option in Setup.
222
Reference
'If Currency values were previously saved in batch
'display them in Currency Selection form.
(Under normal
223
224
DateCheck Function
Description
Verify whether or not a date string in MMDDYYYY format represents a valid date.
Syntax
RetVal = DateCheck(DateString)
Remarks
The DateCheck function uses the following arguments:
Argument
Type
Description
RetVal
Integer
DateString
String
See Also
StrToDate Statement
DateCmp Function
Description
Compare two date values.
Syntax
Cmp = DateCmp(Date1, Date2)
Remarks
To determine whether or not a date value is null use DateCmp(Date, NULLDATE).
NULLDATE is global variable declared in Applic.DH that is properly initialized by
the system at the start of all Tools for Visual Basic applications.
The DateCmp function uses the following arguments:
Argument
Type
Description
Cmp
Integer
Date1
Date2
Reference
DateMinusDate Function
Description
Return the number of days between two dates.
Syntax
NbrDays = DateMinusDate(Date1, Date2)
Remarks
The DateMinusDate function uses the following arguments:
Argument
Type
Description
NbrDays
Long
Date1
Date2
See Also
DatePlusDays Statement, DatePlusMonthSetDay Statement
225
226
DatePlusDays Statement
Description
Add a designated number of days to an existing date.
Syntax
Call DatePlusDays(CurrDate, NbrDaysToAdd, ResultingDate)
Remarks
The DatePlusDays statement uses the following arguments:
Argument
Type
Description
CurrDate
NbrDaysToAdd
Integer
ResultingDate
Result of CurrDate +
NbrDaysToAdd.
See Also
DateMinusDate Function, DatePlusMonthSetDay Statement
Example
The following example shows how the DatePlusDays statement can be used to
calculate a discount date.
If (bTerms.DiscType = "D") Then
'Calculate discount date based on number of days
Call DatePlusDays(bAPDoc.DocDate, bTerms.DiscIntrv,
bAPDoc.DiscDate)
Else
'Calculate due date based on fixed day of the month
Call DatePlusMonthSetDay(bAPDoc.DocDate, 1,
bTerms.DiscIntrv,
bAPDoc.DiscDate)
End If
Reference
227
DatePlusMonthSetDay Statement
Description
Add a designated number of months to an existing date and set the day portion of the
resulting date to a specific day of the month.
Syntax
Call DatePlusMonthSetDay(CurrDate, NbrMthsToAdd, SetSpecificDay,
ResultingDate)
Remarks
The DatePlusMonthSetDay statement uses the following arguments:
Argument
Type
CurrDate
Description
NbrMthsToAdd
Integer
SetSpecificDay
Integer
ResultingDate
See Also
DateMinusDate Function, DatePlusDays Statement
Example
The following example shows how the DatePlusMonthSetDay statement can be used
to calculate a discount date.
If (bTerms.DiscType = "D") Then
'Calculate discount date based on number of days
Call DatePlusDays(bAPDoc.DocDate, bTerms.DiscIntrv, bAPDoc.DiscDate)
Else
'Calculate due date based on fixed day of the month
Call DatePlusMonthSetDay(bAPDoc.DocDate, 1, bTerms.DiscIntrv,
bAPDoc.DiscDate)
End If
228
DateToIntlStr Function
Description
Convert a specified date into the Windows short date style.
Syntax
ShortDateStr = DateToIntlStr(DateToConvert)
Remarks
DateToIntlStr will convert a date from a SQL database format into a format governed
by the Windows short date style.
DateToIntlStr uses the following arguments:
Argument
Type
Description
ShortDateStr
String
DateToConvert
See Also
DateToStr Function, DateToStrSep Function, IntlStrToDate Statement,
StrToDate Statement
Reference
229
DateToStr Function
Description
Convert a date value from a SQL date format into a string in MMDDYYYY format.
Syntax
DateString = DateToStr(DateToConvert)
Remarks
The DateToStr function uses the following arguments:
Argument
Type
Description
DateString
String
DateToConvert
See Also
DateToStr Function, DateToStrSep Function, IntlStrToDate Statement,
StrToDate Statement
DateToStrSep Function
Description
Convert a date value from a SQL date format into a string in MM/DD/YYYY format.
Syntax
DateString = DateToStrSep(DateToConvert)
Remarks
The DateToStrSep and DateToStr functions differ only in the fact that
DateToStrSep inserts a single character separator between the month, day and year
portions of the string.
The DateToStrSep function uses the following arguments:
Argument
Type
Description
DateString
String
DateToConvert
See Also
DateToStr Function, DateToStrSep Function, IntlStrToDate Statement,
StrToDate Statement
230
DBNavFetch Functions
Description
Retrieve a composite record from the database using a SQL statement from the DBNav
property of an SAFMaskedText control.
Syntax
RetVal = DBNavFetch1(Ctrl, Cursor, SQLParmValue, bTable1, bTable1Length)
RetVal = DBNavFetch4(Ctrl, Cursor, SQLParmValue, bTable1, bTable1Length,
bTable2, bTable2Length, bTable3, bTable3Length, bTable4, bTable4Length)
RetVal = DBNavFetch8(Ctrl, Cursor, SQLParmValue, bTable1, bTable1Length,
bTable2, bTable2Length, bTable3, bTable3Length, bTable4, bTable4Length, bTable5,
bTable5Length, bTable6, bTable6Length, bTable7, bTable7Length, bTable8,
bTable8Length)
Remarks
DBNavFetch1, DBNavFetch4 and DBNavFetch8 can be used to fetch a composite
record based on the SQL text from the DBNav property of the SAFMaskedText control
specified in the Ctrl parameter. These functions are not applicable if the DBNav
property does not contain either a SQL statement or stored procedure name.
All SAFMaskedText controls have both a PV and a DBNav property each of which
can contain a SQL statement. The DBNavFetch1 and PVChkFetch1 functions are
similar except that they use SQL statements from two different properties, namely the
DBNav and PV properties. Normally the PVChkFetch1 function will be used in
conjunction with the PV property to facilitate both a Possible Values window as well
as the actual fetch of a record. If the program requirements specify the need to fetch a
record but not supply a Possible Values window then DBNavFetch1 will need to be
used in conjunction with the DBNav property. This situation can arise on screens
containing multiple key fields where the last key field does not need a Possible Value
window. An example of such a case is Employee W2 History (02.260) which has two
key fields: Employee ID and Calendar Year. The requirements for the screen are that the
user be forced to enter a valid employee ID based on the Employee table which should
be viewable via a Possible Values window. However no table exists in the Solomon
system to define a valid calendar year and therefore a Possible Values window is not
applicable since any numeric value is valid. Once the last key field has been entered a
unique record corresponding to both key fields needs to be fetched from the database.
Since Calendar Year is the last key field, and a Possible Value window is not required
for that field, the DBNavFetch1 function was used in conjunction with the DBNav
property of the calendar year control.
DBNavFetch1 is designed for SQL statements returning data from a single table. For
more advanced SQL statements having one or more table joins either DBNavFetch4
or DBNavFetch8 can be used.
Reference
231
Type
Description
RetVal
Integer
Ctrl
Cursor
Integer
SQLParmValue
String
bTable1
bTable1Length
Integer
See Also
DetailLoad Statement, PVChkFetch Functions, SAFMaskedText Control, DBNav
Property
Example
Sub cCalYr_Chk (chkstrg As String, retval As Integer)
Dim W2Federal_Fetch
As Integer
232
DecimalPlaces Statement
Syntax
Call DecimalPlaces( Ctrl, PrecisionBasedOnField)
Description
Facilitates the implementation of flexible decimal precision for a SAFFloat control.
Remarks
The SAFFloat control contains a property called DecimalPlaces. The value of this
property determines the number of digits displayed to the right of the decimal separator
for the underlying control. In most cases the DecimalPlaces property is a constant
value specified at design-time which does not need to be altered at runtime. However,
some applications contain fields whose decimal precision can vary at runtime based on
some condition or data item.
For example, in Solomon some applications display monetary values such as an
invoice amount or a transaction amount. These types of applications typically allow the
user to specify the currency they want to use and then relevant fields, such as
transaction amounts, are displayed and/or entered in that currency. The problem is that
each currency can have a different decimal precision. As an illustration, US Dollars is
typically rounded to two decimal places whereas the XYZ currency may be rounded to
three decimal places. For the developer this means that controls used to display these
types of data items need to have their decimal precision dynamically configured at
runtime. In this case that translates to dynamically modifying the DecimalPlaces
property of relevant SAFFloat controls based on the decimal precision of a particular
currency. Another example would be applications that display inventory item
quantities and/or item prices in which the required decimal precision might vary based
on the type of the inventory item currently displayed.
The DecimalPlaces statement simplifies the management of flexible decimal precision
functionality by linking a SAFFloat control with an underlying VB variable whose
value will be used to automatically re-configure the DecimalPlaces property of the
control at runtime.
Support for flexible decimal precision only exists for the following classes of data
items (i.e., FieldClass values):
FieldClass
Class Name
124
Transaction Amount
125
126
Reference
233
The default decimal precision for data items in the Transaction Amount class is
based on the value of the DecPl field in the particular currency record that is
relevant at any particular point in time (e.g., either transaction currency or base
currency).
The Item Quantity and Item Price classes derive their default decimal precision
from the constant value which was specified at design-time for the DecimalPlaces
property. Item Quantity fields are typically designed with 2 decimal places in
Standard Solomon applications. Similarly, Item Price fields are typically designed
with 3 decimal places.
The DecimalPlaces statement must be called for each control requiring flexible
decimal precision. Multiple controls can be linked to the same underlying precision
control value. The call(s) must occur in the Form_Load event of Form1.
Furthermore, the application must assume the responsibility of setting the value of the
underlying precision control value (i.e., PrecisionBasedOnField). In particular, the
value of the PrecisionBasedOnField must be set prior to actually displaying data in any
corresponding flexible precision control.
For controls outside the context of SAFGrid, this simply means that the
PrecisionBasedOnField should be set when the record containing the flexible
precision data item is loaded. This will typically be in a key field Chk event.
Controls existing within the context of a SAFGrid are handled slightly different.
In this case, the table containing the underlying PrecisionBasedOnField will
normally be joined with the table containing the flexible precision data item which
is to be displayed in the SAFGrid.
Type
Description
Ctrl
Control
PrecisionBasedOnField
Integer
Example
The following example examines a portion of the Form_Load event for the GL Batch
Release process.
This application displays a SAFGrid containing all Batch records that are available for
release. The precision associated with the Batch Control amount may vary for each
detail line since each individual Batch may have been entered in a different currency.
234
Reference
235
DetailLoad Statement
Description
Load a designated SAFGrid control with information from the database using the SQL
statement or stored procedure specified in its DBNav property.
Syntax
Call DetailLoad(SAFGridCtrl)
Remarks
Two types of detail levels (i.e., spreadsheets or grids) are supported by Tools for
Visual Basic: Standard detail levels and Application Loaded detail levels. Standard and
Application Loaded detail levels are respectively defined with a level type of D and
DA in the Levels property of the SAFUpdate control. Standard detail levels are the
most common type of grids. The Application Loaded detail level is a special type of
grid used when a Standard grid cannot be implemented due to various technical
obstacles.
One such technical obstacle is when the SQL statement or stored procedure used to
load information into the SAFGrid control requires more parameters than is supported
by the DBNav property. In that case the DBNav property cannot be used and therefore
the application will need to take responsibility for both loading and saving information
into the relevant SAFGrid control. The DetailLoad statement cannot be used in this
type of scenario.
In other cases the DBNav property can be used but the application needs to control
when the information is actually loaded. Since Standard detail levels are always loaded
automatically by the system, this requirement for control over the timing of the load
operation can be another technical obstacle necessitating the usage of an Application
Loaded detail level. In this case the application merely needs to issue a call to
DetailLoad notifying the system at the precise point when the SAFGrid should
actually be loaded with information. The system will then use the DBNav property of
the designated SAFGrid control to load itself with information from the database. In
this case the application does not need to concern itself with responsibility for saving
the data since the system will still perform that task automatically.
The DetailLoad statement uses the following arguments:
Argument
Type
Description
SAFGridCtrl
Control
See Also
DBNav Property, DetailSetup Functions, MLoad Statement, SAFGrid Control
236
Example
An example of a screen using the DetailLoad statement is the GL Allocation Group
Maintenance screen. This screen needs to control the timing of the load operation since
it needs to work with the data immediately after the data is loaded but before control
returns to the user. The following code snippet is from the Chk event of the header
level master key field called Group ID.
Sub cGrpId_Chk (chkstrg As String, retval As Integer)
Dim AllocGrp_Fetch
As Integer
Reference
237
DetailSave Statement
Description
Update the database with the contents of the designated SAFGrid control.
Syntax
Call DetailSave(Cursor, SAFGridCtrl, TablesUpdating)
Remarks
DetailSave is used in extremely rare cases in which the application either needs to
control precisely when the database is actually updated with the contents of an
SAFGrid control or which individual tables should be updated. Usage of DetailSave is
not required for either Standard or Application Loaded detail levels (i.e., respectively
D and DA level types in the Levels property of the SAFUpdate control).
When the Update event fires for any type of detail level, the actual update to the
database does not occur until after control returns back to the system for that level. In
such a case, the DetailSave call could be issued during the Update event for the
relevant detail level and then RetVal should be set to the NoAction symbolic constant
defined in Applic.DH. By setting RetVal to NoAction, the system will be notified to
avoid saving data from the SAFGrid control again, as it normally would, after control
returns back to the system for that particular detail level.
By default, the system saves data for the master table associated with any type of detail
level. The master table for a level is the table identified in the SetAddr call for that
particular level. If an application has a grid containing information from more than one
table (e.g., a joined view) and also needs to update both tables with modifications made
by the user, then the DetailSave statement will need to be utilized in the Update event
of the SAFUpdate control as previously discussed.
The DetailSave statement uses the following arguments:
Argument
Type
Description
Cursor
Integer
SAFGridCtrl
Control
TablesUpdating
String
See Also
DetailLoad Statement, DetailSetup Functions, SetAddr Statement, SAFUpdate
Control
238
DetailSetup Functions
Description
Initialize a Detail level by binding together all associated components, such as controls,
database cursor and table structures at runtime.
Syntax
MemHandle = DetailSetup(Cursor, SAFGridCtrl, AutoLineNbrFld, bTable1,
bTable1Length, bTable2, bTable2Length, bTable3, bTable3Length, bTable4,
bTable4Length)
MemHandle = DetailSetup8(Cursor, SAFGridCtrl, AutoLineNbrFld, bTable1,
bTable1Length, bTable2, bTable2Length, bTable3, bTable3Length, bTable4,
bTable4Length, bTable5, bTable5Length, bTable6, bTable6Length, bTable7,
bTable7Length, bTable8, bTable8Length)
Remarks
A Detail data entry level in a Tools for Visual Basic application is composed of several
different components which are bound together at runtime via either the DetailSetup
or DetailSetup8 function. For example, each detail data entry level has an SAFGrid
control to manage the user interface for multiple detail lines. Since the data displayed
in the SAFGrid is actually stored in a memory array the array needs to be opened at
runtime. At any point in time the application needs to have table structure variables
capable of holding data for the current record in the grid and/or its underlying memory
array. An SAFGrid control with its underlying memory array and table structure
variables is nevertheless ineffectual without the ability to load and save data - which
necessitates a connection to the database through a cursor. The DetailSetup and
DetailSetup8 functions automatically open a memory array and attach all these
components together with it at runtime.
The DetailSetup function uses the following arguments (DetailSetup8 has eight table
structures and corresponding lengths. PNULL should be passed for unused table
structure parameters as well as a corresponding length of zero such as PNULL, 0).
Argument
Type
Description
MemHandle
Integer
Cursor
Integer
SAFGridCtrl
Control
SAFGrid control.
Reference
239
Argument
Type
Description
AutoLineNbrFld
Integer
bTable1
bTable1Length
Integer
bTable2
bTable2Length
Integer
bTable3
bTable3Length
Integer
bTable4
bTable4Length
Integer
These calls are only required for screens implementing a Detail level (i.e., a D or DA
level in the Update.Levels property). In these cases, the DetailSetup and DetailSetup8
calls must be made within the Form_Load event of Form1. Additionally the call must
occur after ScreenInit and any optional AutoNbrDefault calls.
See Also
DetailLoad Statement, DetailSave Statement, DetailSetupExtend Function,
MGetDelHandle Function, ScreenInit Statement, SAFGrid Control, SAFUpdate
Control
240
Example
The following code illustrates a DetailSetup call in the context of a two level Batch /
Transaction screen. In this case bPRTran.LineNbr line number values will be
automatically managed by SWIMAPI.
Sub Form_Load ()
Call ApplInit
End Sub
Reference
241
DetailSetupExtend Function
Description
Bind an additional table that is not referenced by the SAFGrid.DBNav stored
procedure to a grid already initialized via the use of the DetailSetup or DetailSetup8
function.
Syntax
RetVal = DetailSetupExtend(SAFGridCtrl, bTable1, bTable1Length)
Remarks
This call allows additional tables to be added to an existing grid. It must be noted that
the only difference between DetailSetup() table structures and DetailSetupExtend()
table structures is that records from tables bound via the latter method are not retrieved
via the SAFGridCtrl.DBNav SQL statement or stored procedure. For example,
examine the following call to setup a hypothetical grid:
MemHandle = DetailSetup( CSR_DBNav, Spread_PRTran, PNULL, bPRTran,
LenB(bPRTran), bNonDBMemBuffer, LenB(bNonDBMemBuffer), PNULL, 0, PNULL,
0)
The key to highlight in this Select statement is that data is only being retrieved from
the PRTran table. In other words, NonDBMemBuffer appears nowhere in the entire
SQL statement. If a developer were to attempt to implement a grid with the preceding
DetailSetup call and its associated DBNav SQL statement, an error would occur. In
particular, SWIMAPI would object to the fact that the size of the data referred to in the
DBNav stored procedure (e.g., the size of a single PRTran record) does not match the
total length of all tables whose length was passed in the DetailSetup call (i.e.,
LenB(bPRTran) + LenB(bNonDBMemBuffer) ). Normally such an error message
indicates an error in the application, and as such will elicit a grateful response from the
developer for highlighting the exact nature of the problem. However, occasionally
developers may run across a case where they really do need information from the
database to coexist in a grid with data that does not come from the database.
DetailSetupExtend was created to facilitate this type of functionality.
This API allows the developer to add tables to the grid with the understanding that data
from such table(s) is not referred to by the DBNav SQL statement. Consequently,
SWIMAPI will not include the length of any tables bound via any DetailSetupExtend
call in the length of a single detail line for the purpose of comparing with the size of
a composite data record referred to by the DBNav SQL statement. Rather it will only
compare the size of a composite data record referred to by the SAFGridCtrl DBNav
SQL statement with the total length of all tables in the DetailSetup or DetailSetup8
call.
242
Type
Description
RetVal
Integer
SAFGridCtrl
Control
SAFGrid control.
bTable1
User-defined datatype
bTable1Length
Integer
See Also
DetailSetup Functions, SAFGrid Control
Reference
243
DispField Statements
Description
Display the value of the underlying data field(s) corresponding to the designated
control(s).
Syntax
Call DispField(Control)
Call DispFields(Form, FirstControl, LastControl)
Remarks
Each SAF data control is associated with an underlying Visual Basic variable via a
combination of its FieldName property and an associated SetAddr call. The system
will automatically redisplay the new value of relevant controls anytime the system is
the entity modifying the value of the underlying VB variable, such as when a new
record is loaded. However, when the application directly modifies the value of a VB
variable underlying an SAF data control, then it may also need to call one of the
DispField statements to display the new value in the relevant control.
DispField and DispFields are functionally equivalent except that the latter statement
can be used to display a range of controls based on their TabIndex property order.
The DispFields statement uses the following arguments:
Argument
Type
Description
Form
Control
FirstControl
Control
LastControl
Control
See Also
FieldName Property, MDisplay Statement, SetAddr Statement, TabIndex
Property
244
Example
The following code snippet from the Payroll Earnings Type Maintenance screen
illustrates how the DispField statement should be used after the VB variable
underlying a particular data control has been modified programmatically. The code is
from the Chk event of the Earnings Type combo box control.
Sub cType_Chk (chkstrg As String, retval As Integer)
This is an assumption
End Sub
Reference
245
DispForm Statement
Description
Display a designated subform.
Syntax
Call DispForm(SubFormName, CenterIt)
Remarks
DispForm will cause the designated subform to be displayed modally, meaning that no
other form from the same application can receive focus until the subform is hidden via
a call to HideForm.
Form1 is always displayed automatically by the system. Consequently, this call is only
necessary for subforms. However the subform must have previously been loaded in the
Form1_Load event using the LoadForm statement.
The DispForm statement uses the following arguments:
Argument
Type
Description
SubFormName
Control
CenterIt
Integer
See Also
HideForm Statement, LoadForm Statement
Example
Sub cPayrollTables_Click ()
Call DispForm(F0229002, True)
End Sub
246
DisplayMode Statement
Description
Toggle display only mode.
Syntax
Call DisplayMode(Mode)
Remarks
This call can be used to easily put an application into display only mode using a
single line of code rather than being forced to disable each individual control.
Once DisplayMode has been called, all calls to SetProps referencing the Enabled
property are essentially ignored. The advantage of this type of architecture is that it
reduces code complexity. In particular, the application can issue calls to the SetProps
statement without surrounding each and every call with a conditional statement (such
as If DisplayMode = False).
When an application is placed into display only mode, several of the Parent toolbar
buttons will also be affected. In particular, the Insert, Delete and Save buttons for all
levels will be disabled after their current setting has been saved. When DisplayMode is
subsequently called to take the application out of display only mode, the original
settings for these Parent toolbar buttons will be restored.
All calls to DisplayMode are ignored if the application is automatically placed into
display only mode by the system due to access rights.
The DisplayMode statement uses the following argument:
Argument
Type
Description
Mode
Integer
See Also
DisplayModeSetProps Statement, SetButton Statement, SetProps Statement
Reference
247
DisplayModeSetProps Statement
Description
Modify a control property regardless of whether or not the application is in display
mode.
Syntax
Call DisplayModeSetProps(Form, FirstControl, LastControl, PropertyToModify,
NewPropertyValue)
Remarks
This statement is functionally equivalent to the SetProps statement with the exception
that calls to DisplayModeSetProps will modify property values without regard to
whether the application has been placed in display only mode via the DisplayMode
statement.
DisplayModeSetProps should only be used on those rare occasions when an
application uses the DisplayMode statement to implement display only functionality
but at the same time needs to manipulate the properties of one or more controls.
SetProps cannot be used in these specific instances since such calls are overridden
anytime the application is in display only mode. In the vast majority of cases this will
be an advantage since the application does not need to contain code determining
whether or not it is in display only mode before deciding which SetProps calls to make
and which ones not to make. On the contrary the application can make a single call to
DisplayMode which will automatically override all subsequent calls to SetProps until
DisplayMode is called again to get out of display only mode. If the property of one or
more controls needs to be manipulated while the application is in display mode, then
the DisplayModeSetProps statement should be utilized.
DisplayModeSetProps uses the following arguments:
Argument
Form
FirstControl
LastControl
PropertyToModify
NewPropertyValue
Type
Description
Form containing all controls from FirstControl to
LastControl inclusive. PNULL can be used to
include all forms within the application.
First control to be assigned a new property value for
Control
the PropertyToModify.
Last control to be assigned a new property value. A
Control
particular property can be modified for all controls
on the Form by passing PNULL for both the
FirstControl and LastControl arguments.
Name of the property whose value is to be modified.
String
String or Integer New value to be assigned to the designated property
of all applicable controls. Note: The type of data
actually required for this argument depends on
which property is being modified.
Control
See Also
DisplayMode Statement, SetProps Statement
248
DParm Function
Description
Convert a date into a SQL parameter string.
Syntax
SQLParmStr = DParm(DateToConvert)
Remarks
The DParm function uses the following arguments:
Argument
Type
Description
SQLParmStr
String
DateToConvert
See Also
FParm Function, IParm Function, SParm Function
Reference
249
ExportCustom Function
Description
Export one or more customizations to an ASCII text file.
Syntax
RetVal = ExportCustom(KeySegScreenNbr, KeySegUserID, KeySegBegLevel,
KeySegEndLevel, KeySegLanguageId, KeySegCpnyName, OutputFile, AppendToFile)
Remarks
Customizations can be copied to other databases by first exporting them from the
source database to an ASCII text file using the ExportCustom function. The resulting
export file can subsequently be imported into a destination database using the
ImportCustom function. The Export Customizations (91.500) and Import
Customizations (91.510) application screens utilize these two functions to perform
their export and import work.
Each call to ExportCustom will export all customizations whose unique key
corresponds to the various KeySeg parameters.
The following are valid values for KeySegBegLevel and KeySegEndLevel:
100 - Language
200 - Supplemental Product
300 - All Users
400 - One User
500 - Self
See Also
ImportCustom Function
The ExportCustom function uses the following arguments:
Argument
Type
Description
RetVal
Integer
KeySegScreenNbr
String
KeySegUserID
String
250
Argument
Type
Description
KeySegBegLevel
Integer
KeySegEndLevel
Integer
KeySegLanguageId
String
KeySegCpnyName
String
OutputFile
String
AppendToFile
Integer
Example
The following example illustrates a simple process that will export all of the Custom
records contained in the Mem_Custom memory array.
Note: The initialization of the Mem_Custom array, such as opening and loading the
memory array, is purposely not included so as to focus on the ExportCustom function
call.
Dim
Dim
Dim
Dim
Dim
Mem_Fetch
Mem_MaintFlg
Nbr_Selected_Recs_Processed
File_Append_Flag
Error_Encountered
As
As
As
As
As
Integer
Integer
Integer
Integer
Integer
Reference
251
All
252
FPAdd Function
Description
Add two double-precision floating-point values together with a designated rounding
precision.
Syntax
Result = FPAdd(Dbl1, Dbl2, Precision)
Remarks
Error conditions occurring during the addition operation, such as an overflow error,
will be handled automatically by the system. These types of errors will cause the
appropriate error message to be either displayed on the screen or written to the process
status log depending on the context in which the error occurred. After an error
condition has been properly reported, the application will be terminated.
The FPAdd function uses the following arguments:
Argument
Type
Description
Result
Double
Return value
Dbl1
Double
Dbl2
Double
Precision
Integer
Rounding precision.
Note: The precision parameter can be an explicit precision value as well as one of the
following symbolic constants defined in Applic.DH:
See Also
FPDiv Function, GetPrecision Function, FPMult Function, FPRnd Function,
FPSub Function
Example
The following example illustrates how to add a fixed amount to a double-precision
floating-point value and let the system handle all rounding issues.
bEmployee.YTDEarn = FPAdd(bEmployee.YTDEarn, 1000.12, MONEY)
Reference
253
FParm Function
Description
Convert a double-precision floating-point value into a SQL parameter string.
Syntax
SQLParmStr = FParm(DblToConvert)
Remarks
The FParm function uses the following arguments:
Argument
Type
Description
SQLParmStr
String
DblToConvert
Double
See Also
DParm Function, IParm Function, SParm Function
254
FPDiv Function
Description
Divide one double-precision floating-point value by another with a designated
rounding precision.
Syntax
Result = FPDiv(Dbl1, Dbl2, Precision)
Remarks
This function will divide the value of Dbl1 by Dbl2 and return the result.
Error conditions occurring during the division operation, such as division by zero, will
be handled automatically by the system. These types of errors will cause the
appropriate error message to be either displayed on the screen or written to the process
status log depending on the context in which the error occurred. After an error
condition has been properly reported, the application will be terminated.
The FPDiv function uses the following arguments:
Argument
Type
Description
Result
Double
Return value
Dbl1
Double
Dbl2
Double
Precision
Integer
Rounding precision.
Note: The precision parameter can be an explicit precision value as well as one of the
following symbolic constants defined in Applic.DH:
See Also
FPAdd Function, GetPrecision Function, FPMult Function, FPRnd Function,
FPSub Function
Example
The following example illustrates how to divide a double-precision floating-point value
by a fixed amount and let the system handle all rounding issues.
WeeklySalary = FPDiv(bEmployee.StdSlry, 52, MONEY)
Reference
255
FPMult Function
Description
Multiply two double-precision floating-point values together to a designated rounding
precision.
Syntax
Result = FPMult(Dbl1, Dbl2, Precision)
Remarks
Error conditions occurring during the multiplication operation, such as an overflow
error, will be handled automatically by the system. These types of errors will cause the
appropriate error message to be either displayed on the screen or written to the process
status log depending on the context in which the error occurred. After an error
condition has been properly reported, the application will be terminated.
The FPMult function uses the following arguments:
Argument
Type
Description
Result
Double
Return value
Dbl1
Double
Dbl2
Double
Precision
Integer
Rounding precision.
Note: The precision parameter can be an explicit precision value as well as one of the
following symbolic constants defined in Applic.DH:
See Also
FPAdd Function, FPDiv Function, GetPrecision Function, FPRnd Function,
FPSub Function
Example
The following example illustrates how to multiply a double-precision floating-point
value by a fixed amount and let the system handle all rounding issues.
bEmployee.StdSlry = FPMult(WeeklySalary, 52, MONEY)
256
FPRnd Function
Description
Round a double-precision floating-point value to a designated rounding precision.
Syntax
Result = FPRnd(DblToRound, Precision)
Remarks
Error conditions occurring during the rounding operation, such as an overflow error,
will be handled automatically by the system. These types of errors will cause the
appropriate error message to be either displayed on the screen or written to the process
status log depending on the context in which the error occurred. After an error
condition has been properly reported, the application will be terminated.
The FPRnd function uses the following arguments:
Argument
Type
Description
Result
Double
Return value
DblToRound
Double
Value to be rounded
Precision
Integer
Rounding precision.
Note: The precision parameter can be an explicit precision value as well as one of the
following symbolic constants defined in Applic.DH:
See Also
FPAdd Function, FPDiv Function, GetPrecision Function, FPMult Function,
FPSub Function
Reference
257
Example
Dim Result
As Double
"Last operation
exceeds
'field size, please reenter"
Call Mess(1)
Else
'Round to a monetary value
bAPTran.TranAmt = FPRnd(Result, MONEY)
End If
258
FPSub Function
Description
Subtract one double-precision floating-point value from another with a designated
rounding precision.
Syntax
Result = FPSub(Dbl1, Dbl2, Precision)
Remarks
This function will subtract the value of Dbl2 from Dbl1 and return the result.
Error conditions occurring during the subtraction operation, such as an overflow error,
will be handled automatically by the system. These types of errors will cause the
appropriate error message to be either displayed on the screen or written to the process
status log depending on the context in which the error occurred. After an error
condition has been properly reported, the application will be terminated.
The FPSub function uses the following arguments:
Argument
Type
Description
Result
Double
Return value
Dbl1
Double
Dbl2
Double
Precision
Integer
Rounding precision.
Note: The precision parameter can be an explicit precision value as well as one of the
following symbolic constants defined in Applic.DH:
See Also
FPAdd Function, FPDiv Function, GetPrecision Function, FPMult Function,
FPRnd Function
Example
The following example illustrates how to subtract a fixed amount from a doubleprecision floating-point value and let the system handle all rounding issues.
bEmployee.YTDEarn = FPSub(bEmployee.YTDEarn, 1000.12, MONEY)
Reference
259
FtoA Function
Description
Convert a double-precision floating-point value into an ASCII string with the
designated rounding precision.
Syntax
Str = FtoA( DblToConvert, Precision)
Remarks
The FtoA function uses the following arguments:
Argument
Type
Description
Str
String
Returned string
DblToConvert
Double
Precision
Integer
Rounding precision.
Note: The precision parameter can be an explicit precision value as well as one of the
following symbolic constants defined in Applic.DH:
See Also
FPRnd Function, GetPrecision Function
260
GetCuryRate Statement
Description
Retrieves Currency Rate information from the Currency Rate table in the database,
based upon the Transaction Currency ID, Base Currency ID, Rate Type, and Effective
Date values in the Currency Selection Form fields at the time of the call. Updates the
Rate, Rate Reciprocal, and Multiply/Divide fields of the Currency Selection Form from
the record retrieved from the database. The record with a matching Transaction
Currency ID, Base Currency ID, and Rate Type, and an Effective Date on or before the
specified Effective Date will be retrieved, if it exists. If a Currency Rate table entry is
not found, an error message is displayed. If new rate information is successfully
retrieved, all Base Currency values for all monetary fields specified for multi-currency
processing are recalculated, based upon the new rate.
Syntax
Call GetCuryRate
Remarks
New rate information is typically retrieved into the Currency Selection form when data
entered into the application causes one of the key fields used to establish previous
Currency Rate Information to change. For example, if the user enters a vendor ID into
a document, and the application logic re-defaults the Rate Type field in the Currency
Selection Form to the default value for the Vendor, the application will typically need
to retrieve the Currency Rate Information corresponding to the new rate type.
The GetCuryRate statement does not require any arguments.
Example
The following example shows the Vendor Chk event for an application being enabled
for multi-currency processing. If the Vendor record contains a valid rate type, the rate
type in the Currency Selection Form is re-defaulted to the Vendor default value, and
new Currency Rate Information is retrieved using the GetCuryRate statement. Note
that CuryRateTypeSet is called before GetCuryRate. Since GetCuryRate uses the
current contents of the Currency Selection Form as key values to look up the new rate,
it is important that any necessary updates to the key values in the Currency Selection
Form be performed before calling GetCuryRate.
Sub cvendid_Chk (chkstrg As String, retval As Integer)
Dim maintflg As Integer
'Fetch vendor record to display Name, status and Terms
retval = pvchkfetch1(cvendid, C3, chkstrg, bVendor, LenB(bVendor))
Reference
261
'Currency Manager
If retval = 0 Then
'If multi-currency entry is activated...
If bCMSetup.MCActivated = LTRUE Then
'If Vendor Currency ID is specified, and
'is different from Batch Currency ID...
If Trim$(bVendor.CuryID) <> "" And Trim$(bVendor.CuryID) <>
Trim$(bCuryInfo.TranCuryId) Then
'Give error or warning, depending upon
'setup option.
If bCMSetup.APCuryOverride = LFALSE Then
retval = 6090
Exit Sub
Else
Call mess(6091)
End If
End If
'If Tran Currency is different from Base Currency...
If Trim$(bCuryInfo.TranCuryId) <> Trim$(bPES.BaseCuryID)
'Then If Vendor Rate Type is specified, and
'is different from Batch Rate Type...
If Trim$(bVendor.CuryRateType) <> "" And
Trim$(bVendor.CuryRateType) <> Trim$(bCuryInfo.RateType)
Then
'Check whether Vendor Rate Type exists
serr1 = ChkCuryRateType(bVendor.CuryRateType)
If serr1 <> 0 Then
'If not, exit with error
retval = 6092
Exit Sub
Else
'If it does, try to retrieve Rate Table entry
Call CuryRateTypeSet(bVendor.CuryRateType)
Call GetCuryRate
End If
End If
End If
End If
End If
End Sub
262
GetModulePeriod Function
Description
Retrieve the current fiscal period of a designated Solomon module.
Syntax
CurrFiscalPeriod = GetModulePeriod( SIVModuleNbr)
Remarks
There are two ways to determine the current fiscal period of a Solomon module. The
first and most obvious method is to retrieve the setup record for the appropriate module
directly from the database. An easier method, however, is to simply call the
GetModulePeriod function specifying the relevant module number.
The GetModulePeriod function has the following arguments:
Argument
Type
CurrFiscalPeriod
String
String
SIVModuleNbr
Description
See Also
PeriodMinusPeriod Function, PeriodPlusPerNum Function
Reference
263
GetPrecCury Function
Description
Return the rounding precision associated with the designated Currency ID.
Syntax
Precision = GetPrecCury( CurrencyID)
Remarks
Each currency defined within Solomon can use a different decimal precision.
Consequently, all floating point calculations on currency related fields, such as
transaction amounts, should round their result to match the rounding precision of the
relevant currency. The GetPrecCury function facilitates this objective by allowing
applications to easily obtain the rounding precision associated with a particular
currency.
In applications where only one transaction currency and one base currency are in effect
at any given time, the preferred method for specifying the precision parameter in a
floating point calculation is to use either the TRANCURY or BASECURY constant
defined in Applic.DH. However, in applications where multiple transaction currencies
and/or base currencies are displayed or processed, the precision must be obtained for
the particular currency represented in the calculation
The GetPrecCury function uses the following arguments:
Argument
Type
Description
Precision
Integer
CurrencyID
String
264
Example
Sub TranTotal_Update (ByVal Acct As String, ByVal Subacct As String,
ByVal CuryID As String, ByVal BaseCuryID As String, ByVal CuryCreditAmt
As Double, ByVal CuryDebitAmt As Double, ByVal CreditAmt As Double, ByVal
DebitAmt As Double, CuryTranCRTot As Double, CuryTranDBTot As Double,
TranCrTot As Double, TranDBTot As Double)
'Currency Manager - use currency field reference for test
If ((CuryCreditAmt <> 0#) And (CuryDebitAmt <> 0#)) Then
'Tran can NEVER have both a credit AND debit amount - as we would not
'know for sure which value to use in our system.
Call Status(MSG_TRAN_S1_S2_CANT_CR_AND_DR_AMT, True, SParm(Acct) +
SParm(Subacct), LOG_AND_DISP)
Else
See Also
DecimalPlaces Statement, FPAdd Function, FPDiv Function, FPMult Function,
FPRnd Function, FPSub Function, Get Precision Function
Reference
265
GetPrecision Function
Description
Return the rounding precision for the designated rounding constant.
Syntax
RoundingPrecision = GetPrecision (RoundingConstant)
Remarks
This function allows the application to obtain the actual rounding precision value
associated with one of the rounding constants defined in Applic.DH.
The GetPrecision function uses the following arguments:
Argument
Type
Description
RoundingPrecision
Integer
RoundingConstant
Integer
See Also
FPAdd Function, FPDiv Function, FPMult Function, FPRnd Function, FPSub
Function
266
GetSqlType Function
Description
Determine which type of database server is being utilized.
Syntax
SqlType = GetSqlType()
Remarks
Solomon currently supports two types of SQL databases: Pervasive.SQL and Microsoft
SQL Server. Although both of these are SQL database servers they nevertheless are not
precisely similar in all respects. Consequently it is likely that many applications will
want to take advantage of highly sophisticated code optimizations which are specific to
a particular type of database server. In such a case, the application should only execute
database specific code when the appropriate type of SQL database is actually being
utilized. This function will facilitate this conditional execution of such code by
informing the application of which type of SQL database is being used.
The GetSqlType function returns one of the following integer global constants
declared in Applic.DH:
Return Value
Description
BTISqlType
MSSqlType
Example
Dim SqlDatabaseBeingUtilized
As Integer
SqlDatabaseBeingUtilized = GetSqlType()
End If
Reference
267
GetSWIMDefaultPrintInfo Function
Description
Retrieve the default Solomon print information and settings.
Syntax
result = GetSWIMDefaultPrintInfo( printInfo )
Remarks
The GetSWIMDefaultPrintInfo function uses the following arguments:
Argument
Type
Description
Result
Boolean
printInfo
PInfo
PInfo Structure
The PInfo structure describes all of the settings used to create report output and send it
to a printer, disk file, or preview window.
Setting
Type
Description
DeviceName
DriverName
PrintPort
PrintDestinationName
String * 256
String * 256
String * 256
String * 256
PrintFileType
String * 2
PrintToFile
Integer
PrintIncludeCodes
DevMode
Integer
Name of printer
Name of print driver
Port of printer
Name of destination file for
exported report
File type code (documented in
standard and advanced reporting
guide under RIPARAM
RI_FILETYPE)
1=Printing to file, 0=not printing
to file
No longer used
Fields specified in PInfo to avoid
alignment problem. See Windows
definition of DEVMODE
structure for description of
values/settings.
dmDeviceName
dmSpecVersion
dmDriverVersion
dmSize
dmDriverExtra
dmFields
String * 32
Integer
Integer
Integer
Integer
Integer
268
Setting
Type
Description
dmMyFiller
dmOrientation
dmPaperSize
dmPaperLength
dmPaperWidth
dmScale
dmCopies
dmDefaultSource
dmPrintQuality
dmColor
dmDuplex
dmYResolution
dmTTOption
dmCollate
dmFormName
dmLogPixels
dmBitsPerPel
dmPelsWidth
dmPelsHeight
dmDisplayFlags
dmDisplayFrequency
dmICMMethod
dmICMIntent
dmMediaType
dmDitherType
dmICCManufacturer
dmICCModel
dmPanningWidth
dmPanningHeight
FontInfo
Integer
Integer
Integer
Integer
Integer
Integer
Integer
Integer
Integer
Integer
Integer
Integer
Integer
Integer
String * 32
Integer
Long
Long
Long
Long
Long
Long
Long
Long
Long
Long
Long
Long
Long
fiFontName
fiFontSize
fiBold
fiItalic
WindowsDefault
PrinterOrientation
String * 32
Integer
Integer
Integer
Integer
Integer
See Also
GetSWIMPrintInfo function, SetSWIMPrintInfofunction
Reference
GetSWIMPrintInfo Function
Description
Retrieve the current print information and settings.
Syntax
result = GetSWIMPrintInfo( printInfo )
Remarks
The GetSWIMPrintInfo function uses the following arguments:
Argument
Type
Description
Result
Boolean
printInfo
PInfo
See Also
GetSWIMDefaultPrintInfo Function, SetSWIMPrintInfo Function, PInfo
structure
269
270
GetSysDate Statement
Description
Retrieve the current system date.
Syntax
Call GetSysDate(Date)
Remarks
The GetSysDate statement uses the following arguments:
Argument
Type
Date
Description
See Also
GetSysTime Statement
GetSysTime Statement
Description
Retrieve the current system time.
Syntax
Call GetSysTime(Time)
Remarks
The GetSysTime statement uses the following arguments:
Argument
Type
Description
Time
See Also
GetSysDate Statement
Reference
271
Grid_Sortable Statement
Description
Informs the system that the specified Grid control is to be treated as a user-sortable
grid. This means that the end-user of the screen will be able to sort the information on
the grid by clicking on the column header.
Syntax
Call Grid_Sortable(LEVEL0, Spread1)
Remarks
The Grid_Sortable statement uses the following arguments:
Argument
Type
Description
Level
Integer, 0 - 10
Spread
Control
SAFGrid control.
The Grid control specified in the Spread1 parameter must abide by the following
conditions:
There can be no key fields defined on the controls that make up the form view of
the Grid control.
When this statement is executed, all the fields on the Grid will be disabled. All
Update buttons will be disabled for the level specified in the first parameter. Insert,
Update and Delete operations will not be allowed for the level once this statement
executes.
272
HideForm Statement
Description
Hide a designated subform previously displayed via a call to DispForm.
Syntax
Call HideForm(SubFormName)
Remarks
This function is typically used in the click event of the OK or Cancel button of the
designated subform.
The HideForm statement uses the following arguments:
Argument
Type
Description
SubFormName
Control
Form to be hidden.
See Also
DispForm Statement, LoadForm Statement
Example
Sub cOK_PayrollTables_Click ()
Call HideForm(F0229002)
End Sub
HideNoteButtons Statement
Description
Hides or displays the Note button for the specified level.
Syntax
Call HideNoteButtons(LevelNbr, HideFlag)
Remarks
The HideNoteButtons statement should be called to hide the note button for a certain
level. Specifying True for the second parameter hides the button. Specifying False
displays the button (if one exists) for the level specified in the first parameter. This
statement can also be called using the AllLevels constant to hide the note buttons for
all the levels in the application.
See Also
NoteButton property, NoteColumn property
Reference
273
ImportCustom Function
Description
Import customizations from an ASCII customization export file.
Syntax
RetVal = ImportCustom(ImportFile, ConflictResolution, ErrorHandling)
Remarks
Customizations can be imported directly into a Solomon database from a customization
export file which previously by either the Export Customizations (91.500) screen or the
ExportCustom function.
Each call to ImportCustom will import all customizations contained within the
ImportFile. In the event an error occurs during the import operation a description of the
error will be written to the process status log.
The ImportCustom function uses the following arguments:
Argument
Type
Description
RetVal
Integer
ImportFile
String
ConflictResolution
Integer
ErrorHandling
Integer
274
Using the Overwrite option, the new customization will overwrite the current
customization.
However, if you are certain that you never want to overwrite any existing
customizations, then you can specify the Reject Customization option. In the event
of a conflict, this option will cause the new customization to be rejected.
The most sophisticated option allows you to Merge new customizations together
with existing customizations. This is an extremely powerful feature which allows
two customizations to be merged into one new customization down to the property
level. For example, assume the position of ControlA has been customized so that
its on-screen position varies from the standard screen. Now suppose that we want
to import a customization in which a reference will be made to ControlA. In
particular the new customization is going to disable ControlA. If the sophisticated
Merge option is utilized, then the result will be that ControlA will have both its
screen position and enabled properties customized! The only case in which a
Merge cannot be successfully carried out by the system is in the case where a
conflict occurs at the property or BSL code procedure level. In our example, if the
new customization being imported also customizes the screen position of
ControlA, then a conflict at the property level will result. In such a case the new
customization will take precedence over the existing customization.
Reference
275
The Reject Entire File option will cause the entire Import File to be rejected if any
Import Errors occur while importing any of the customizations contained therein.
Since an Import File can contain many customizations this option facilitates an
all or nothing type of import operation.
276
See Also
ExportCustom Function
Example
Begin Customization with various key fields identifying a unique customization.
Begin ControlType ControlName
Customized Properties
End
Begin ControlType ControlName
Customized Properties
End
Begin Macro Text
Sub ProceedureName( )
End Sub
End Customization
Begin Customization
customization...
End Customization
.
.
.
Delete ...Various key fields identifying a unique customization...
The following code fragment illustrates how to import all customizations contained in
a file called CUSTOM.CST. Conflicts with existing customizations will be resolved by
specifying that the new customization should overwrite the existing customization. All
customizations contained within the CUSTOM.CST import file will be rejected if any
syntax errors are encountered.
Dim Record_Count
As Integer
Reference
IncrStrg Statement
Description
Increment a string representation of a whole number value.
Syntax
Call IncrStrg(StringNbr, Length, Increment)
Remarks
The IncrStrg statement uses the following arguments:
Argument
Type
Description
StringNbr
String
Length
Integer
Increment
Integer
Example
Dim BatNbrLength
As Integer
BatNbrLength = LenB(Trim$(bGLSetup.LastBatNbr))
'Increment last batch number to the next sequential value (within the
'size of batch numbers actually being used - e.g. BatNbrLength).
Call IncrStrg(bGLSetup.LastBatNbr, BatNbrLength, 1)
277
278
InitLocalizationSubsystem Function
Description
Called to initiate local language user interface support in VB programs where language
translations are implemented using Microsoft Resource files. Determines whether the
text of the program user interface will be loaded from language-translated resources,
contained in a language-specific resource-only .DLL file, or from the standard U.S.
English resources compiled into the program executable. Saves a handle to the
resources for later use by functions that apply resource values to the program user
interface.
Syntax
Boolvar = InitLocalizationSubsystem(ScreenName)
Remarks
The Microsoft Resource file approach to local language user interface support must be
used in only programs that cannot be accessed by Customization Manager. To use this
function, LLI.BAS and LLI.DLL must be added to the VB project, and all languagespecific text that is visible as part of the user interface must be moved to a Microsoft
Resource file and replaced by resource IDs in the main code.
The first 5 characters of the Resource file name must be the same as the first 5
characters of the VB executable name. The 6th through 8th characters must contain the
3-letter Microsoft locale ID for U.S. English, which is EMU. When the program
executable name is fewer than 5 characters, prior to appending the locale ID, zeros
must be appended in the remaining positions to fill the first 5 characters.
System-related text, such as the numeric portion of the screen name, found in the
Form1.Caption must not be moved to the Resource file. The
InitLocalizationSubsystem function must be called, prior to any other logic, in the
Form1.Form_Load event.
The InitLocalizationSubsystem function uses the following arguments:
Argument
Type
Description
Boolvar
Boolean
ScreenName
String
See Also
LoadStr Function, Localize Statement
Reference
279
Example
The following example shows the beginning logic of the Form_Load event for an
application being enabled for local language user interface support, using the resource
file method.
InitLocalizationSubsystem("2400000.exe")
ScreenTitle = LoadStr(IDS_CURRENCYSELECTION)
ScreenTitle = ScreenTitle + " " + SCREENNUMBER
With Form1
.Caption = ScreenTitle
Call Localize(.ltocuryid)
Call Localize(.lratetype)
Call Localize(.lratereciprocal)
.
.
.
Call Localize(.cbuttoncancel)
EndWith
Call ApplInit
280
IntlStrToDate Statement
Description
Convert a date string from the Windows short date style into a SQL database date
format.
Syntax
Call IntlStrToDate(DateStrToConvert, SQLDate)
Remarks
IntlStrToDate can be used to convert a string formatted according to the Windows
short date style into a format suitable for storage in a date field within the SQL
database.
The IntlStrToDate statement uses the following arguments:
Argument
Type
Description
DateStrToConvert
String
SQLDate
See Also
DateToIntlStr Function, DateToStr Function, DateToStrSep Function, StrToDate
Statement
Reference
281
IParm Function
Description
Convert an integer into a SQL parameter string.
Syntax
SQLParmStr = IParm(IntToConvert)
Remarks
The IParm function uses the following arguments:
Argument
Type
Description
SQLParmStr
String
IntToConvert
Integer
See Also
DParm Function, FParm Function, SParm Function
Example
These examples assume the following SQL statement was used to create a stored
procedure called GLTran_Module_BatNbr_LineNbr
Select * from GLTran
where Module
and BatNbr
= @parm1
= @parm2
This code snippet illustrates how the previously defined stored procedure can be used
to fetch a single transaction having a LineNbr of 84 in GL Batch #000123.
SqlStr = "GLTran_Module_BatNbr_LineNbr" + SParm("GL") +
SParm("000123") + IParm(84) + IParm(84)
GLTran_Fetch = SqlFetch1(CSR_GLTran, SqlStr, bGLTran, LenB(bGLTran))
This code snippet illustrates the previously defined stored procedure can be used to
fetch all transactions in GL Batch #000123.
SqlStr = "GLTran_Module_BatNbr_LineNbr" + SParm("GL") +
SParm("000123") + IParm(INTMIN) + IParm(INTMAX)
GLTran_Fetch = SqlFetch1(CSR_GLTran, SqlStr, bGLTran, LenB(bGLTran))
While ( GLTran_Fetch = 0)
GLTran_Fetch = SFetch1( CSR_GLTran, bGLTran, LenB(bGLTran))
Wend
282
IS_AppServer Function
Returns a flag indicating whether or not the application is being executed by
Application Server.
Remarks
Return Value:
IS_TI Function
Description
Returns a flag indicating whether or not the application is being automated by
Transaction Import.
Remarks
Return Value:
IsMultiCompany Function
Description
Returns a flag indicating whether or not MultiCompany is enabled in the current
system.
Remarks
Return Value:
Reference
283
Level_SetDefaults Statement
Description
Set all controls on a particular level to their default value using either their Default
Property or Default Event code.
Syntax
Call Level_SetDefaults(Form, FirstControl, LastControl, LevelNbr)
Remarks
Level_SetDefaults is functionally equivalent to the SetDefaults statement except that
the former can be used to explicitly default all controls having a particular level
number in their Level property.
The Level_SetDefaults statement uses the following arguments:
Argument
Form
FirstControl
LastControl
LevelNbr
Type
Control
Control
Control
Control
Description
PNULL should be passed.
PNULL should be passed.
PNULL should be passed.
Level number for which all relevant controls
should be defaulted.
See Also
Default Event, Default Property, SetDefaults Statement
Example
The Payroll Earnings Type Maintenance screen uses the following code to force
default values to be applied during the NewLevel event as opposed to after the
NewLevel event. This allows that particular application to reset various property values
based on actual default data values - including customized default values. Conceptually
speaking, this can be useful when Field B should be disabled depending on the value of
Field A. In such a case the decision as to whether or not to disable Field B cannot be
made until the value of Field A is actually set.
Sub Update1_New (level%, retval%)
If (level = LEVEL0) Then
'Force ALL default values to be applied to EARNTYPE level
'BEFORE Evaluate_Properties() is called.
Call Level_SetDefaults(PNULL, PNULL, PNULL, LEVEL0)
Call Evaluate_Properties(FLD_ALL)
'Set retval to keep the system from setting default values
'again for LEVEL0.
RetVal = NoAction
End If
End Sub
284
LoadForm Statement
Description
Load a subform.
Syntax
Call LoadForm(SubFormName)
Remarks
All subforms contained within a particular application must be loaded prior to the
ApplInit call in the Form1_Load event using the LoadForm statement.
The call to LoadForm does not cause the subform to be displayed. However, once a
subform has been successfully loaded it can be subsequently displayed using the
DispForm statement.
The LoadForm statement uses the following arguments:
Argument
Type
Description
SubFormName
Control
Form to be loaded.
See Also
ApplInit Statement, DispForm Statement, HideForm Statement
Example
The following code snippet illustrates how the subforms for the Payroll Employee
Maintenance screen are loaded in the Load event of Form1.
Sub Form_Load ()
Dim PRSetup_Fetch
As Integer
Call LoadForm(F0225001)
'Timesheet Defaults
Call LoadForm(F0225002)
'Miscellaneous Info
Call LoadForm(F0225003)
'Pay Information
Call LoadForm(F0225004)
Call LoadForm(F0225005)
'Employee Benefits
(BenEmp
grid)
Call ApplInit
Call SetAddr(LEVEL0, "bEmployee", bEmployee, nEmployee, LenB(bEmployee))
Call SetAddr(LEVEL1, "bWorkLoc", bWorkLoc, nWorkLoc, LenB(bWorkLoc))
Call SetAddr(LEVEL2, "bEarnType", bEarnType, nEarnType, LenB(bEarnType))
Call SetAddr(LEVEL3, "bPayGroup", bPayGroup, nPayGroup, LenB(bPayGroup))
Call SetAddr(LEVEL4, "bEarnDed", bEarnDed, nEarnDed, LenB(bEarnDed))
Call SetAddr(LEVEL5, "bBenEmp", bBenEmp, nBenEmp, LenB(bBenEmp))
Reference
285
'Normal Level
'Lookup Level
'Lookup Level
'Lookup Level
'Detail Level
'Detail Level
286
LoadStr Function
Description
Called in VB programs in which language translations are implemented using
Microsoft Resource files. Loads a string resource element into a string variable.
Syntax
Stringvar = LoadStr(ResourceID)
Remarks
This function must be preceded by the InitLocalizationSubsystem function. See the
reference for InitLocalizationSubsystem for information on the requirements for
enabling local language user interface support in programs using the Microsoft
Resource file approach.
The LoadStr function uses the following arguments:
Argument
Type
Description
Stringvar
String
ResourceID
Long
See Also
InitLocalizationSubsystem Function, Localize Statement
Example
The following example shows the beginning logic of the Form_Load event for an
application being enabled for local language user interface support, using the resource
file method. IDS_CURRENCYSELECTION is a constant representing the Resource
ID number of the string containing the screen title text Currency Selection.
SCREENNUMBER is a constant containing the screen number string (24.000.00).
The screen number is not moved to the resource file, because it contains system-related
text that should not be translated.
InitLocalizationSubsystem("2400000.exe")
ScreenTitle = LoadStr(IDS_CURRENCYSELECTION)
ScreenTitle = ScreenTitle + " " + SCREENNUMBER
With Form1
.Caption = ScreenTitle
Call Localize(.ltocuryid)
Call Localize(.lratetype)
Call Localize(.lratereciprocal)
.
.
Call Localize(.cbuttoncancel)
EndWith
Call ApplInit
Reference
287
Localize Statement
Description
Called in VB programs in which language translations are implemented using
Microsoft Resource files. Loads resource values into the language- translatable
properties of a control.
Syntax
Localize(Ctrl)Remarks
Remarks
This statement must be preceded by the InitLocalizationSubsystem function. See the
reference for InitLocalizationSubsystem for information on the requirements for
enabling local language user interface support in programs using the Microsoft
Resource file approach.
For any control, the Localize statement looks for the following potentially translatable
properties:
Caption
List
TabCaption()
Help
Heading
Text
List()
ColumnText
If the property contains a Resource ID as its value, the Resource ID will be replaced by
the corresponding resource string.
String values for control properties not handled by the Localize function can be loaded
from resources by using the LoadStr function.
The Localize function uses the following arguments:
Argument
Type
Description
Ctrl
Control
See Also
InitLocalizationSubsystem Function, LoadStr Function
288
Example
The following example shows the beginning logic of the Form_Load event for an
application being enabled for local language user interface support, using the resource
file method.
InitLocalizationSubsystem("2400000.exe")
ScreenTitle = LoadStr(IDS_CURRENCYSELECTION)
ScreenTitle = ScreenTitle + " " + SCREENNUMBER
With Form1
.Caption = ScreenTitle
Call Localize(.ltocuryid)
Call Localize(.lratetype)
Call Localize(.lratereciprocal)
.
.
.
Call Localize(.cbuttoncancel)
EndWith
Call ApplInit
Reference
289
MArrayCnt Function
Description
Return the number of records in a designated memory array.
Syntax
NumRecs = MArrayCnt(MemHandle)
Remarks
The MArrayCnt function uses the following arguments:
Argument
Type
Description
NumRecs
Integer
MemHandle
Integer
See Also
MOpen Functions, DetailSetup Functions
Example
This code snippet came from the Update event of Journal Entry Screen. Note that the
MemHandle variable was the return value of the DetailSetup call issued in the
Form1_Load event.
Sub Update1_Update (level%,insertflg%,levelsdone%,levelsleft%,RetVal%)
If (level = Level0) Then
'If the batch level changed then we will just
'go ahead and presume that either Batch.JrnlType
'and/or Batch.PerPost changed. In such a case ALL of the
'GLTrans need to have their respective fields updated
'with the new batch value(s) IF the
'batch has ALREADY been released.
If ((bBatch.Status = "U") And (MarrayCnt(MemHandle) > 0))
Then
Call Mset(cJrnlTypeD, bBatch.JrnlType)
Call Mset(cFiscYr, Left$(bBatch.PerPost, 4))
Call Mset(cPerPostD, bBatch.PerPost)
If (TestLevelChg(Level1) = NOTCHANGED) Then
Call SetLevelChg(Level1, UPDATED)
End If
290
Else
'Don't set the JrnlType/FiscYr/PerPost of
'transactions if the batch status
'is H/B since they will get set automatically
'by the 01.400 release process.
End If
End If
End Sub
Reference
291
MCallChks Statement
Description
Callable by an application for doing row-by-row error checking for an SAFGrid.
Syntax
Call MCallChks(MemArray, BeginControl, EndControl)
Remarks
The MCallChks function uses the following arguments:
Argument
Type
Description
MemArray
Integer
BeginControl
Control
EndControl
Control
Return Value
Integer
MClear Statement
Description
Delete all records from the designated memory array.
Syntax
Call MClear(MemHandle)
Remarks
The MClear statement can be used to clear an existing memory array of its contents.
The array will stay allocated and can be subsequently re-used.
The MClear statement uses the following arguments:
Argument
Type
Description
MemHandle
Integer
See Also
MOpen Functions, DetailSetup Functions
292
MClose Statement
Description
Close an existing memory array.
Syntax
Call MClose(MemHandle)
Remarks
MClose can be used to close a memory array previously opened using one of the
MOpen functions. Memory arrays created automatically by the DetailSetup functions
should not be closed by the application.
The MClose statement uses the following arguments:
Argument
Type
Description
MemHandle
Integer
See Also
MOpen Functions
Example
This example illustrates how to close a memory array no longer needed by the
application.
Dim Mem_Account
As Integer
Dim CSR_Account
As Integer
Dim SqlStr
Dim Account_Fetch
As String
As Integer
Reference
'Read through all subsequent Account records, inserting each
'one into the memory array.
While( Account_Fetch = 0)
'Insert current Account record into the memory array
Call MInsert( Mem_Account)
'Fetch the next Account record
Account_Fetch = SFetch1(CSR_Account, bAccount,
LenB(bAccount))
Wend
'Close the memory array
Call MClose( Mem_Account)
293
294
MDelete Function
Description
Delete the current record from the designated memory array.
Syntax
RecFetch = MDelete(MemHandle, RecMaintFlg)
Remarks
The current record in a memory array can be deleted by using the MDelete function.
After the record is deleted, the system will automatically navigate to the next memory
array record since there must always be a current record in memory arrays, assuming
of course that one or more records exist. Consequently, the return value and
corresponding record status apply to the next record after the deleted record.
When this call is used on a memory array associated with an SAFGrid control (e.g.,
memory arrays opened automatically via the DetailSetup function), an MDisplay call
will be necessitated to properly synchronize the SAFGrid appearance with the
memory array.
The MDelete function uses the following arguments:
Argument
Type
Description
RecFetch
Integer
MemHandle
Integer
RecMaintFlg
Integer
See Also
DetailSetup Functions, MDisplay Statement, MInsert Statement, MUpdate
Statement
Reference
295
MDisplay Statement
Description
Display the current contents of the designated memory array in its corresponding
SAFGrid control.
Syntax
Call MDisplay(MemHandle)
Remarks
Each SAFGrid control is associated with an underlying memory array that is opened
automatically by the system during the DetailSetup call. Anytime data within this
memory array is modified directly by the application, as opposed to by the user, the
SAFGrid control must be subsequently redisplayed.
When MDisplay is called, the current memory array record will be displayed at the top
of the SAFGrid control. Thus, for example, if the application wants the first memory
array record to display at the top of the SAFGrid control it should initially call MFirst
to move to the first record and then call MDisplay.
The MDisplay statement uses the following arguments:
Argument
Type
Description
MemHandle
Integer
See Also
DetailSetup Functions
Example
The following example illustrates how the Release Payroll Batches process redisplays
the SAFGrid control associated with the MemHandle memory array after processing
has completed.
Sub cBegProcessing_Click ()
Dim RecFound
As Integer
Dim MemMaintFlg
Dim Nbr_Of_Batches_Processed
As Integer
As Integer
296
Reference
297
Mess Statement
Description
Displays a message from the Solomon message file and waits for the user to choose a
button.
Syntax
Call Mess(MsgNumber)
Remarks
When Solomon is installed, an ASCII text file called MESSAGES.CSV is copied to
the \SOL4 directory. This file contains all messages relating to the Solomon product including all independently developed applications created with Tools for Visual
Basic. Each message has, among other things, a message number. A particular message
can be displayed to the screen by merely passing its associated message number to the
Mess statement.
The Messf statement should be used if the actual text of the message contains
replaceable parameters.
The MessResponse function can be used to determine which button was chosen by the
user to close the message box.
The standard VB MsgBox statement should not be used in applications developed with
Tools for Visual Basic in order to avoid conflicts with other Solomon Utilities such as
Cut/Copy/Paste and Transaction Import. These utilities have built-in sophistication to
respond to messages from the underlying application during the particular operation
being performed such as paste or import. However, this automated functionality does
not apply to messages displayed using the standard VB MsgBox statement. The
MessBox statement has been provided to facilitate similar functionality to the standard
VB MsgBox statement with the exception that MessBox does not conflict with other
Solomon Utilities.
The Mess statement uses the following arguments:
Argument
Type
Description
MsgNumber
Integer
298
Comments
Message Number
Category
Language
0 for English.
Type
Box Type
Record Type
Message Text
The Box Type field within the MESSAGES.CSV file can have the following values:
Box Type Value
Icon
Buttons
Default Button
None
OK
OK
16
Stop
OK
OK
48
Exclamation
OK
OK
64
Information
OK
OK
36
Question
Yes / No
Yes
292
Question
Yes / No
No
33
Question
OK / Cancel
OK
See Also
MessBox Statement, Messf Statement, MessResponse Function
Reference
299
Example
The Payroll Employee Maintenance screen allows the user to enter the number of
personal exemptions claimed by any particular employee on the Miscellaneous
Information sub-screen. Anytime this value is changed the user is prompted, via a
message, as to whether or not the new total number of personal exemptions is to be
utilized by each individual deduction for calculation purposes.
Message number 739 is the actual message displayed and its associated text in the
Solomon message file reads as follows: Do you want to update the employees
deductions with the new exemption value?. This particular message will also display
two buttons in the message box - a Yes button and a No button. The MessResponse
function is subsequently called to determine which of these two buttons the user
actually selected to close the message box.
Sub cDfltPersExmpt_Chk (chkstrg As String, retval As Integer)
Dim MemArray_NbrRecs
As Integer
MemArray_NbrRecs = MArrayCnt(MemArray_EmpDeduction)
'If the memory array has any records in it then prompt the user
'whether or not he/she wants to update the number of PERSONAL
'EXEMPTIONS on ALL existing employee deductions.
If (MemArray_NbrRecs > 0) Then
Call Mess( 739)
If (MessResponse() = IDYES) Then
Call MSet(F0225004.cNbrPersExmpt, chkstrg)
Call MDisplay(MemArray_EmpDeduction)
End If
End If
End Sub
300
MessBox Statement
Description
Displays a message and waits for the user to choose a button.
Syntax
Call MessBox(Msg, Type, Title)
Remarks
The standard VB MsgBox statement should not be used in applications developed with
Tools for Visual Basic in order to avoid conflicts with other Solomon Utilities such as
Cut/Copy/Paste and Transaction Import. These utilities have built-in sophistication to
respond to messages from the underlying application during the particular operation
being performed such as paste or import. However, this automated functionality does
not apply to messages displayed using the standard VB MsgBox statement. The
MessBox statement has been provided to facilitate similar functionality to the standard
VB MsgBox statement with the exception that MessBox does not conflict with other
Solomon Utilities.
The MessResponse function can be used to determine which button was chosen by the
user to close the message box.
The MessBox statement uses the following arguments:
Argument
Type
Description
Msg
String
Type
Integer
Title
String
See Also
Mess Statement, Messf Statement, MessResponse Function
Reference
301
Messf Statement
Description
Formats a message from the Solomon message file with replaceable parameters and
then displays it and waits for the user to choose a button.
Syntax
Call Messf(MsgNumber, Parm1Str, Parm2Str, Parm3Str, Parm4Str, Parm5Str,
Parm6Str)
Remarks
When Solomon is installed, an ASCII text file called MESSAGES.CSV is copied to
the \SOL4 directory. This file contains all messages relating to the Solomon product including all independently developed applications created with Tools for Visual
Basic. Each message has, among other things, a message number. The message can
also contain up to six replaceable parameters by placing a %s at the appropriate
point(s) within the actual message text. A particular message can be subsequently
displayed to the screen by merely passing its associated message number to the Messf
statement along with data values for each replaceable parameter.
The Mess statement should be used if the actual text of the message does not contain
replaceable parameters.
The MessResponse function can be used to determine which button was chosen by the
user to close the message box.
The standard VB MsgBox statement should not be used in applications developed with
Tools for Visual Basic in order to avoid conflicts with other Solomon Utilities such as
Cut/Copy/Paste and Transaction Import. These utilities have built-in sophistication to
respond to messages from the underlying application during the particular operation
being performed such as paste or import. However, this automated functionality does
not apply to messages displayed using the standard VB MsgBox statement. The
MessBox statement has been provided to facilitate similar functionality to the standard
VB MsgBox statement with the exception that MessBox does not conflict with other
Solomon Utilities.
The Messf statement uses the following arguments:
Argument
Type
Description
MsgNumber
Integer
Parm1Str
String
Parm2Str
String
Parm3Str
String
Parm4Str
String
302
Argument
Type
Description
Parm5Str
String
Parm6Str
String
Each record (e.g., message) contained within the MESSAGES.CSV file contains the
following fields separated by a comma:
Field Name
Comments
Message Number
Category
Language
0 for English.
Type
Box Type
Record Type
Message Text
The Box Type field within the MESSAGES.CSV file can have the following values:
Box Type Value
Icon
Buttons
Default Button
None
OK
OK
16
Stop
OK
OK
48
Exclamation
OK
OK
64
Information
OK
OK
36
Question
Yes / No
Yes
292
Question
Yes / No
No
33
Question
OK / Cancel
OK
See Also
FtoA Function, Mess Statement, MessBox Statement, MessResponse Function
Reference
303
Example
The Payroll Manual Check screen uses the following code to warn the user of the fact
that a Batch is out of balance.
Message number 818 is the actual message displayed and its associated text in the
Solomon message file reads as follows: Batch is out of balance by %s. Do you want
to edit?. This particular message will also display two buttons in the message box - a
Yes button and a No button. The MessResponse function is subsequently called to
determine which of these two buttons the user actually selected to close the message
box.
'Make sure that the batch itself is in balance with the documents.
Batch_Out_Of_Bal_Amt = FPSub(bBatch.CtrlTot, bBatch.DrTot, MONEY)
If (Batch_Out_Of_Bal_Amt <> 0#) Then
Call Messf(818, FtoA(Batch_Out_Of_Bal_Amt, MONEY), "", "", "", "",
"")
If (MessResponse() = IDYES) Then
'User decided to edit the batch - so abort the
Finish
retval = ErrNoMess
'Set focus on the Batch Control Total field
Call ApplSetFocus(cCtrlTot)
End If
End If
304
MessGetText Function
Description
Returns the message text associated with a particular message number.
Syntax
TextStr = MessGetText(MsgNumber)
Remarks
The MessGetText function uses the following argument:
Argument
Type
Description
TextStr
String
MsgNumber
Integer
See Also
Mess Statement, Messf Statement
Reference
305
MessResponse Function
Description
Returns the button chosen by the user to close the last message box displayed using the
Mess, Messf or MessBox statements.
Syntax
ButtonId = MessResponse()
Remarks
The MessResponse function returns one of the following symbolic constants declared
in Applic.DH:
Return Value
IDOK
IDYES
IDNO
IDCANCEL
IDABORT
IDRETRY
IDIGNORE
Description
OK button selected.
Yes button selected.
No button selected.
Cancel button selected.
Abort button selected.
Retry button selected.
Ignore button selected.
See Also
Mess Statement, Messf Statement
Example
The Payroll Manual Check screen uses the following code to warn the user of the fact
that a Batch is out of balance.
Message number 818 is the actual message displayed and its associated text in the
Solomon message file reads as follows: Batch is out of balance by %s. Do you want
to edit?. This particular message will also display two buttons in the message box - a
Yes button and a No button. The MessResponse function is subsequently called to
determine which of these two buttons the user actually selected to close the message
box.
'Make sure that the batch itself is in balance with the documents.
Batch_Out_Of_Bal_Amt = FPSub(bBatch.CtrlTot, bBatch.DrTot, MONEY)
If (Batch_Out_Of_Bal_Amt <> 0#) Then
Call Messf( 818, FtoA(Batch_Out_Of_Bal_Amt, MONEY), "", "", "", "", "")
If (MessResponse() = IDYES) Then
'User decided to edit the batch - so abort the Finish
retval = ErrNoMess
'Set focus on the Batch Control Total field
Call ApplSetFocus(cCtrlTot)
End If
End If
306
MFirst Function
Description
Move to the first record in a designated memory array.
Syntax
RecFetch = MFirst(MemHandle, RecMaintFlg)
Remarks
MFirst moves to the first record of a specified memory array and copies the contents
of the array record into the data structure(s) previously specified in either the MOpen
or DetailSetup function call used to originally open the relevant memory array.
When this call is used on a memory array associated with an SAFGrid control (i.e.,
memory arrays opened automatically via the DetailSetup function), an MDisplay call
will be necessitated to properly synchronize the SAFGrid appearance with the
memory array.
The MFirst function uses the following arguments:
Argument
Type
Description
RecFetch
Integer
MemHandle
Integer
RecMaintFlg
Integer
See Also
MLast Function, MNext Function, MPrev Function
Reference
307
MGetDelHandle Function
Description
Returns the resource handle of the memory array used to temporarily hold detail lines
deleted from the designated SAFGrid control.
Syntax
DelMemHandle = MGetDelHandle(SAFGridCtrl)
Remarks
Each SAFGrid control is associated with two underlying memory arrays that are
opened automatically by the system during the DetailSetup call. The primary memory
array is used to hold the records which are actually visible in the grid. The resource
handle to this primary memory array is actually returned by the DetailSetup functions.
However, another array is also created to temporarily hold records which the user has
deleted until a SAVE operation is performed and the deletions are actually committed
to the database. The resource handle to this memory array can be retrieved using the
MGetDelHandle function.
Once the resource handle for the deleted record memory array has been retrieved, it
can be used by the application to loop through records deleted by the user using calls
such as MFirst and MNext.
The MGetDelHandle function uses the following arguments:
Argument
Type
Description
DelMemHandle
Integer
SAFGridCtrl
Control
SAFGrid control
See Also
DetailSetup Functions
308
MGetLineStatus Function
Description
Returns the line status of the current record in the designated memory array.
Syntax
RecMaintFlg = MGetLineStatus(MemHandle)
Remarks
The MGetLineStatus function allows the application to retrieve the status of the
current memory array record at any time.
The MGetLineStatus function uses the following arguments:
Argument
Type
Description
RecMaintFlg
Integer
MemHandle
Integer
See Also
MSetLineStatus Function
Reference
309
MGetRowNum Function
Description
Returns the row / record number of the current record in the designated memory array.
Syntax
CurrRecNbr = MGetRowNum(MemHandle)
Remarks
The MGetRowNum function uses the following arguments:
Argument
Type
Description
CurrRecNbr
Integer
MemHandle
Integer
See Also
MArrayCnt Function, MSetRow Statement
310
MInsert Statement
Description
Insert a new record into a designated memory array.
Syntax
Call Minsert(MemHandle)
Remarks
MInsert is used to add a new record to a memory array. This is accomplished by
copying the contents of all data structures previously associated with the designated
memory array into a new memory array record. Data structures are associated with a
memory array in either the MOpen or DetailSetup function call used to originally
open the relevant memory array. The new memory array record will have a line status
of INSERTED.
When this call is used on a memory array associated with an SAFGrid control (e.g.,
memory arrays opened automatically via the DetailSetup function), an MDisplay call
will be necessitated to properly synchronize the SAFGrid appearance with the
memory array.
The MInsert statement uses the following arguments:
Argument
Type
Description
MemHandle
Integer
See Also
DetailSetup Functions, MDelete Function, MOpen Functions, MSetLineStatus
Function, MUpdate Statement
Reference
311
Example
This example illustrates how records can be inserted into a memory array under
program control.
Dim Mem_Account
As Integer
Dim CSR_Account
As Integer
Dim SqlStr
As String
Dim Account_Fetch
As Integer
'Allocate cursor
Call SqlCursor( CSR_Account, NOLEVEL)
'Read through all subsequent Account records, inserting each one into the
'memory array.
While( Account_Fetch = 0)
'Insert current Account record into the memory array
Call MInsert( Mem_Account)
'Fetch the next Account record
Account_Fetch = SFetch1(CSR_Account, bAccount, LenB(bAccount))
Wend
312
MKey Statement
Description
Define a key field for a previously opened memory array.
Syntax
Call MKey(MemHandle, KeySegmentNbr, TableDotFieldName, Ascending)
Remarks
Occasionally a program will need the ability to easily locate a particular record within
a memory array based on one or more key field values. The MKeyFind function can
be used to accomplish this goal assuming the sort order for the memory array has been
previously defined. Memory arrays associated with an SAFGrid control automatically
have their sort order initialized by the DetailSetup function based on the key field
control(s) contained within the grid (e.g., notated by a ,k in the levels property of the
controls). All other memory arrays must have their sort order explicitly defined via one
of several different methods. Each of the methods to define a key field, such as MKey,
MKeyFld, MKeyHctl and MKeyOffset, vary primarily in the way they acquire
detailed information on a key field such as datatype, size and byte offset within a userdefined datatype.
The MKey statement is the simplest and most common of all these methods to define a
memory array key field. MKey is so simple because the system will automatically
determine the requisite key field information for the TableDotFieldName based both
on the SetAddr call for the relevant table and its corresponding data dictionary
information in the database. The two restrictions of the MKey method are that it can
only be used for fields whose table exists in the database (e.g., as opposed to a memory
variable existing only within VB code) and a SetAddr call must have already been
issued for the relevant table.
Multi-segment keys can be defined by successive calls to MKey with different
KeySegmentNbr argument values.
The MKey statement uses the following arguments:
Argument
Type
Description
MemHandle
Integer
KeySegmentNbr
Control
TableDotFieldName
String
Ascending
Integer
Reference
313
See Also
MKeyFind Function, MKeyFld Statement, MKeyHctl Statement, MKeyOffset
Statement, MOpen Functions, MSort Statement
Example
This example illustrates how to open a memory array and define multiple key fields.
Dim Mem_ValEarnDed
As Integer
'Set up use of
MKeyFind()
314
MKeyFind Function
Description
Find a specific record in a sorted memory array based on designated key field values.
Syntax
RecFetch = MKeyFind(MemHandle, KeySeg1Val, KeySeg2Val, KeySeg3Val,
KeySeg4Val, KeySeg5Val)
Remarks
Occasionally a program will need the ability to easily locate a particular record within
a memory array based on one or more key field values. The MKeyFind function can
be used to accomplish this goal assuming the sort order for the memory array has been
previously defined. Memory arrays associated with an SAFGrid control automatically
have their sort order initialized by the DetailSetup function based on the key field
control(s) contained within the grid (e.g., notated by a ,k in the levels property of the
controls). All other memory arrays must have their sort order explicitly defined via one
of several different methods. Each of the methods to define a key field, such as MKey,
MKeyFld, MKeyHctl and MKeyOffset, vary primarily in the way they acquire
detailed information on a key field such as datatype, size and byte offset within a userdefined datatype.
If a record whose key fields exactly match the KeySeg?Val arguments does not exist,
the system positions to the closest match. It will however still return a NOTFOUND to
the application.
The MKeyFind function uses the following arguments:
Argument
Type
Description
RecFetch
Integer
MemHandle
Integer
KeySeg1Val
KeySeg2Val
KeySeg3Val
KeySeg4Val
KeySeg5Val
Reference
315
See Also
MKey Statement, MKeyFld Statement, MKeyHctl Statement, MKeyOffset
Statement, MOpen Functions, MSetRow Statement, MSort Statement
Example
This example illustrates how to open a memory array and load the entire Solomon
Chart of Accounts into the newly created array and then find a specific account record.
Dim Mem_Account
As Integer
Dim CSR_Account
As Integer
Dim SqlStr
As String
Dim Account_Fetch
As Integer
316
MKeyFld Statement
Description
Define a key field for a previously opened memory array.
Syntax
Call MKeyFld(MemHandle, KeySegmentNbr, TableDotFieldName, bTable,
Ascending)
Remarks
Occasionally a program will need the ability to easily locate a particular record within
a memory array based on one or more key field values. The MKeyFind function can
be used to accomplish this goal assuming the sort order for the memory array has been
previously defined. Memory arrays associated with an SAFGrid control automatically
have their sort order initialized by the DetailSetup function based on the key field
control(s) contained within the grid (e.g., notated by a ,k in the levels property of the
controls). All other memory arrays must have their sort order explicitly defined via one
of several different methods. Each of the methods to define a key field, such as MKey,
MKeyFld, MKeyHctl and MKeyOffset, vary primarily in the way they acquire
detailed information on a key field such as datatype, size and byte offset within a userdefined datatype.
The MKeyFld method is similar to the MKey method except that it does not require a
SetAddr call for the relevant table.
Multi-segment keys can be defined by successive calls to MKeyFld with different
KeySegmentNbr argument values.
The MKeyFld statement uses the following arguments:
Argument
Type
Description
MemHandle
Integer
KeySegmentNbr
Integer
TableDotFieldName
String
bTable
Reference
317
Argument
Type
Description
Ascending
Integer
See Also
MKey Statement, MKeyFind Function, MKeyHctl Statement, MKeyOffset
Statement, MOpen Functions, MSort Statement
Example
This example illustrates how to open a memory array and define multiple key fields.
Dim Mem_ValEarnDed
As Integer
'Set up use of
MKeyFind()
318
MKeyHctl Statement
Description
Define a key field for a previously opened memory array.
Syntax
Call MKeyHctl(MemHandle, KeySegmentNbr, KeyFieldControl, Ascending)
Remarks
Occasionally a program will need the ability to easily locate a particular record within
a memory array based on one or more key field values. The MKeyFind function can
be used to accomplish this goal assuming the sort order for the memory array has been
previously defined. Memory arrays associated with an SAFGrid control automatically
have their sort order initialized by the DetailSetup function based on the key field
control(s) contained within the grid (e.g., notated by a ,k in the levels property of the
controls). All other memory arrays must have their sort order explicitly defined via one
of several different methods. Each of the methods to define a key field, such as MKey,
MKeyFld, MKeyHctl and MKeyOffset, vary primarily in the way they acquire
detailed information on a key field such as datatype, size and byte offset within a userdefined datatype.
The MKeyHctl method acquires information on the designated key field from a
control having the key field itself in its FieldName property.
Multi-segment keys can be defined by successive calls to MKeyHctl with different
KeySegmentNbr and KeyFieldControl argument values.
The MKeyHctl statement uses the following arguments:
Argument
Type
Description
MemHandle
Integer
KeySegmentNbr
Integer
KeyFieldControl
Control
Ascending
Integer
See Also
MKey Statement, MKeyFind Function, MKeyFld Statement, MKeyOffset
Statement, MOpen Functions, MSort Statement
Reference
319
MKeyOffset Statement
Description
Define a key field for a previously opened memory array.
Syntax
Call MKeyOffset(MemHandle, KeySegmentNbr, bTable, KeyFldByteOffset,
KeyFldDataType, KeyFldDataLength, Ascending)
Remarks
Occasionally a program will need the ability to easily locate a particular record within
a memory array based on one or more key field values. The MKeyFind function can
be used to accomplish this goal assuming the sort order for the memory array has been
previously defined. Memory arrays associated with an SAFGrid control automatically
have their sort order initialized by the DetailSetup function based on the key field
control(s) contained within the grid (e.g., notated by a ,k in the levels property of the
controls). All other memory arrays must have their sort order explicitly defined via one
of several different methods. Each of the methods to define a key field, such as MKey,
MKeyFld, MKeyHctl and MKeyOffset, vary primarily in the way they acquire
detailed information on a key field such as datatype, size and byte offset within a userdefined datatype.
The MKeyOffset method is the most flexible method of defining memory array key
fields but it is also the most detailed to code. It is designed to facilitate the definition of
a key field that does not exist in the database and therefore has no correlated data
dictionary information in the database. This situation can occur if one of the userdefined datatypes in a memory array is only declared within VB and does not exist
within the database. In such a case, the system has no way of determining the byte
offset from the beginning of the structure for any particular field, the field datatype nor
the length of the field. The MKeyOffset statement allows the developer to explicitly
pass all of this detailed information relating to the designated key field since it does not
exist in the SQL data dictionary.
Multi-segment keys can be defined by successive calls to MKeyOffset with different
KeySegmentNbr argument values.
320
Type
Description
MemHandle
Integer
KeySegmentNbr
Integer
bTable
KeyFldByteOffset
Integer
KeyFldDataType
Integer
KeyFldDataLength
Integer
Ascending
Integer
See Also
MKey Statement, MKeyFind Function, MKeyFld Statement, MKeyHctl
Statement, MOpen Functions, MSort Statement
Reference
321
Example
The following example illustrates a memory array containing only selected fields from
the Employee table that is nevertheless sorted by employee ID. By only storing
selected Employee fields in the memory array, much less memory will be consumed
for each record within the memory array.
Since not all fields in the Employee database table are contained within the
Employee_SelFld user-defined datatype, the data dictionary information in the SQL
database corresponding to the standard Employee table is not usable by the system for
purposes of determining the required key field information. Consequently,
MKeyOffset must be utilized to implement sorting on the Employee ID key field.
Code to declare the user-defined datatype containing only selected fields from the
Employee table. Notice that the Name field is being deliberately declared before the
EmpId field so as to further illustrate the complete flexibility of MKeyOffset.
Type Employee_SelFld
Name
As String * 30
EmpId
As String * 10
End Type
Global bEmployee_SelFld
As Employee_SelFld
Code to open a memory array for the bEmployee_SelFld user-defined datatype and
define Employee ID as the key field.
Dim Mem_Employee_SelFld
As Integer
322
As Integer
Dim SqlStr
As String
Dim Employee_SelFld_Fetch
As Integer
'Allocate a cursor
Call SqlCursor(CSR_Employee_SelFld, NOLEVEL)
'Initialize cursor with a SQL statement and immediately fetch
'the first record
SqlStr = "Select Name, EmpId from Employee Order By EmpId"
Employee_SelFld_Fetch = SqlFetch1(CSR_Employee_SelFld, SqlStr,
bEmployee_SelFld, LenB(bEmployee_SelFld))
'Read through all subsequent Employee records, inserting each one into
'the memory array.
While(Employee_SelFld_Fetch = 0)
'Insert current Employee record into the memory array
Call MInsert( Mem_Employee_SelFld)
'Fetch the next Employee record
Employee_SelFld_Fetch = SFetch1(CSR_Employee_SelFld,
bEmployee_SelFld, LenB(bEmployee_SelFld))
Wend
Reference
323
MLast Function
Description
Move to the last record in a designated memory array.
Syntax
RecFetch = MLast(MemHandle, RecMaintFlg)
Remarks
MLast moves to the last record of a specified memory array and copies the contents of
the array record into the data structure(s) previously specified in either the MOpen or
DetailSetup function call used to originally open the relevant memory array.
When this call is used on a memory array associated with an SAFGrid control (e.g.,
memory arrays opened automatically via the DetailSetup function), an MDisplay call
will be needed to properly synchronize the grid appearance with the memory array.
The MLast function uses the following arguments:
Argument
Type
Description
RecFetch
Integer
MemHandle
Integer
RecMaintFlg
Integer
See Also
MFirst Function, MNext Function, MPrev Function
324
MLoad Statement
Description
Load a memory array with all records returned from the database by a SQL statement.
Syntax
Call MLoad(MemHandle, Cursor)
Remarks
There are two ways to load data directly from the database into a memory array. The
most obvious method is to insert one record at a time into the memory array until no
additional records are returned from the database. A simpler method is to load the
entire array via a single call to the MLoad statement. The only requirement is that the
Cursor passed as a parameter to the MLoad statement must already be initialized with
a SQL Select statement or stored procedure so it is ready to begin returning data. The
cursor can be initialized by passing the SQL Select statement or stored procedure,
along with any necessary parameters, to the SQL statement.
The MLoad statement uses the following arguments:
Argument
Type
Description
MemHandle
Integer
Cursor
Integer
See Also
DetailLoad Statement, Sql Statement
Reference
Example
This example illustrates how to open a memory array and load the entire Solomon
Chart of Accounts into the newly created array using a single call to the MLoad
statement.
Dim Mem_Account
As Integer
Dim CSR_Account
As Integer
Dim SqlStr
As String
'Allocate cursor
Call SqlCursor( CSR_Account, NOLEVEL)
325
326
MNext Function
Description
Move to the next record in a designated memory array.
Syntax
RecFetch = MNext(MemHandle, RecMaintFlg)
Remarks
MNext moves to the next record of a specified memory array and copies the contents
of the array record into the data structure(s) previously specified in either the MOpen
or DetailSetup function call used to originally open the relevant memory array.
When this call is used on a memory array associated with an SAFGrid control (e.g.,
memory arrays opened automatically via the DetailSetup function), an MDisplay call
will be necessitated to properly synchronize the SAFGrid appearance with the
memory array.
The MNext function uses the following arguments:
Argument
Type
Description
RecFetch
Integer
MemHandle
Integer
RecMaintFlg
Integer
See Also
MFirst Function, MLast Function, MPrev Function
Reference
327
MOpen Functions
Description
Open a new memory array and return a corresponding unique memory array number.
Syntax
MemHandle = MOpen(DelRetToSystem, bTable1, bTable1Length, bTable2,
bTable2Length, bTable3, bTable3Length, bTable4, bTable4Length)
MemHandle = MOpen8(DelRetToSystem, bTable1, bTable1Length, bTable2,
bTable2Length, bTable3, bTable3Length, bTable4, bTable4Length, bTable5,
bTable5Length, bTable6, bTable6Length, bTable7, bTable7Length, bTable8,
bTable8Length)
Remarks
A memory array must be opened before insert, update, delete or memory array
navigation operations can be performed on it. The memory array handle returned by
MOpen and MOpen8 is used when performing these types of operations on memory
arrays.
MOpen allocates memory for up to four table structures whereas MOpen8 can handle
up to eight different table structures for each memory array record.
MOpen is only used to open memory arrays which are not associated with an
SAFGrid control. Memory arrays which correspond to grids are opened automatically
by either the DetailSetup or DetailSetup8 function.
The MOpen function uses the following arguments (MOpen8 has eight table
structures and corresponding lengths. PNULL should be passed for unused table
structure parameters as well as a corresponding length of zero such as PNULL, 0)
Argument
Type
Description
MemHandle
Integer
DelRetToSystem
Control
bTable1
User-defined datatype
bTable1Length
Integer
328
Argument
Type
Description
bTable2
User-defined datatype
bTable2Length
Integer
bTable3
User-defined datatype
bTable3Length
Integer
bTable4
User-defined datatype
bTable4Length
Integer
The table structures passed to MOpen do not have to be actual database tables. They
can be either a simple data item, such as a double, or any user-defined data type created
with the VB Type statement.
See Also
MClear Statement, MClose Statement, MDelete Function, MDisplay Statement,
MFirst Function, MInsert Statement, MKey Statement, MKeyFind Function,
MLast Function, MNext Function, MPrev Function, MUpdate Statement
Reference
329
Example
This example illustrates how to open a memory array and load the entire Solomon
Chart of Accounts into the newly created array.
Dim Mem_Account
As Integer
Dim CSR_Account
As Integer
Dim SqlStr
As String
Dim Account_Fetch
As Integer
'Allocate cursor
Call SqlCursor( CSR_Account, NOLEVEL)
330
MPrev Function
Description
Move to the previous record in a designated memory array.
Syntax
RecFetch = MPrev(MemHandle, RecMaintFlg)
Remarks
MPrev moves to the previous record of a specified memory array and copies the
contents of the array record into the data structure(s) previously specified in either the
MOpen or DetailSetup function call used to originally open the relevant memory
array.
When this call is used on a memory array associated with an SAFGrid control (e.g.,
memory arrays opened automatically via the DetailSetup function), an MDisplay call
will be necessitated to properly synchronize the SAFGrid appearance with the
memory array.
The MPrev function uses the following arguments:
Argument
Type
Description
RecFetch
Integer
MemHandle
Integer
RecMaintFlg
Integer
See Also
MFirst Function, MLast Function, MNext Function
Reference
331
MSet Statement
Description
Explicitly set the value of a particular control for every record in its corresponding
SAFGrid control.
Syntax
Call MSet(Control, NewDataValue)
Remarks
The MSet statement uses the following arguments:
Argument
Type
Description
Control
Control
NewDataValue
String
See Also
MSetProp Statement
332
MSetLineStatus Function
Description
Set the line status of the current record in the designated memory array.
Syntax
RetVal = MSetLineStatus(MemHandle, NewLineStatus)
Remarks
Each record within a memory array has its own line status such as INSERTED,
UPDATED or NOTCHANGED. The system automatically modifies the line status
based on the type of activity last performed on any particular memory array record. For
example, if a record is inserted into a memory array using MInsert, then the status of
that new memory array record will automatically be set to INSERTED. Occasionally,
however, the application may need to assign a specific line status to a particular
memory array record. In such cases the MSetLineStatus function can be used to carry
out this task.
One common usage of this function is when a memory array associated with an
SAFGrid control is being loaded from the database under application control. In these
cases records are being inserted into the memory array via successive MInsert calls.
However since the data is in no way modified between the time it is fetched and the
time it is inserted into the memory array the line status of the resultant memory array
record is forced to change from INSERTED to NOTCHANGED.
The MSetLineStatus function uses the following arguments:
Argument
Type
Description
RetVal
Integer
MemHandle
Integer
RecMaintFlg
Integer
See Also
MGetLineStatus Function, MInsert Statement, MUpdate Statement
Reference
333
Example
This example illustrates how to load a memory array from the database and at the same
time force the line status of all newly inserted memory array records to be
NOTCHANGED.
Dim Mem_Account
As Integer
Dim CSR_Account
As Integer
Dim SqlStr
As String
Dim Account_Fetch
As Integer
334
MSetProp Statement
Description
Set the value of a particular property for both the designated form-view control as well
as its associated SAFGrid control.
Syntax
Call MSetProp(Control, PropertyName, NewPropValue)
Remarks
At runtime, each column of an SAFGrid control is associated with an underlying (e.g.,
form-view) Tools for Visual Basic custom control. The MSetProp statement can be
used to modify a property setting for both the underlying control as well as the relevant
column in the associated grid. For example, an entire column can be disabled using the
MSetProp statement.
If the application wants to modify property values on a line by line basis, as opposed to
an entire column, then it will need to manage the property settings using calls to the
SetProps statement from within the LineGotFocus event of each individual detail line.
Note: MSetProp cannot be called from within the FormLoad event of a Visual Basic
application. MSetProp relies on the grid control to be completely configured before
changing its properties. The grid is not completely configured until the form is
displayed on the screen. This display occurs after the FormLoad event has occurred.
The MSetProp statement uses the following arguments:
Argument
Type
Description
Control
Control
PropertyName
String
NewPropValue
String or Integer
See Also
BlankErr Property, Enabled Property, Heading Property, Mask Property, Min
Property, Max Property, SetProps Statement, SAFGrid Control, Visible Property
Reference
335
Example
The Release Payroll Batches process screen contains an SAFGrid control which
automatically displays all Payroll batches that are ready to be released. The SAFGrid
control only exists to facilitate the users need to specify which batches should be
released. Consequently, for example, the Insert, Save, and Delete buttons on the
Solomon toolbar do not need to be enabled since the user is not allowed insert new
batches nor update existing batches. This is accomplished using the SetButton
statement. However, since disabling all of these buttons causes all controls within the
SAFGrid to be disabled, the application needs to subsequently re-enable the one
control used to select individual batches for processing.
'Disable buttons so user will not be able to take any action on batches
'in the grid
Call SetButton(DeleteButton + InsertButton + SaveButton +
CancelButton, AllLevels, False)
'Re-enable the control used to Select/Deselect batches.
Call MSetProp(cCurrBatSelected, PROP_ENABLED, True)
336
MSetRow Statement
Description
Set the current row / record number of a designated memory array.
Syntax
Call MSetRow(MemHandle, NewCurrRecNbr)
Remarks
An application can jump to a specific memory array record via either the MKeyFind
function or the MSetRow statement. MSetRow jumps to a specific record number
whereas MKeyFind locates the record with designated key field values.
The MSetRow statement uses the following arguments:
Argument
Type
Description
MemHandle
Integer
NewCurrRecNbr
Integer
See Also
MGetRowNum Function, MKeyFind Function
Reference
337
MSort Statement
Description
Sort data contained within an existing memory array based upon predefined key fields.
Syntax
Call MSort( MemHandle)
Remarks
This statement will sort all existing records within the designated memory array based
upon key fields previously defined using one of the MKey, MKeyFld, MKeyHctl or
MKeyOffset statements.
If the data within the memory array is initially loaded and maintained in the proper
order, a call to MSort will not be necessary. MSort only needs to be called if one or
more records within the memory array are not in an order consistent with the
previously defined key fields. When the data is out of order, MKeyFind will not work
properly since it assumes that the data within the memory array is consistent with the
predefined sort sequences.
Memory arrays associated with an SAFGrid control require an MDisplay call to
redisplay the grid, subsequent to calling MSort.
See Also
MDisplay Statement, MKey Statement, MKeyFind Function, MKeyFld
Statement, MKeyHctl Statement, MKeyOffset Statement, MOpen Functions
338
MUpdate Statement
Description
Update the current memory array record of a designated memory array with new data
values.
Syntax
Call MUpdate(MemHandle)
Remarks
MUpdate is used to update an existing record of a specified memory array. This is
accomplished by copying the new contents of all data structures previously associated
with the designated memory array over the existing memory array record. Data
structures are associated with a memory array in either the MOpen or DetailSetup
function call used to originally open the relevant memory array. If the memory array
record had a line status of INSERTED prior to the MUpdate call then the line status
will remain INSERTED. In all other cases, the memory array record will have a line
status of UPDATED.
The MUpdate statement uses the following arguments:
Argument
Type
Description
MemHandle
Integer
See Also
DetailSetup Functions, MDelete Function, MInsert Statement, MOpen Functions,
MSetLineStatus Function
Reference
339
NoteCopy Function
Description
Find the source sNote record using the SourceNoteid, then create a new sNote record
with the same Note text.
Syntax
Call NoteCopy(SourceNoteId, DestRecordType)
Remarks
NoteCopy returns a long that is the new noteid for the sNote that was created. If
NoteCopy returns a 0, then it was not successful (possibly a note did not exist for the
source record).
A transaction needs to be open at the time that NoteCopy is called so that the sNote
record that is created can be saved. The save of the sNote record happens within the
NoteCopy function, but the save of the destination record does not. Once the noteid is
returned and the destination.noteid field is filled, it is up to the developer to determine
whether the record will need to be saved explicitly or whether SWIM will save it.
The NoteCopy function uses the following arguments:
Argument
Type
Description
SourceNoteId
Integer
DestRecordType
String
Example
This example is taken from code that is creating a new shipper from an existing one. If
a note exists on the existing shipper, it is copied to the new shipper record.
If (bSOShipHeader.NoteID = 0) Then
bSOShipHeader.NoteID = NoteCopy(bSOHeader.NoteID, "SOShipHeader")
End If
340
PasteTemplate Function
Description
Paste information from the designated template into the current application.
Syntax
RetVal = PasteTemplate(TemplateID)
Remarks
The Solomon Template feature makes it possible to store data from the current screen
and subsequently paste that data into the same screen at a later time. Templates can be
saved to the database programmatically using the SaveTemplate statement as well as
via the Template menu item on the Edit menu. Once a template has been created it can
be pasted into its source application under program control using the PasteTemplate
function as well as via the Template menu item on the Edit menu.
The PasteTemplate statement uses the following arguments:
Argument
Type
Description
RetVal
Integer
TemplateID
String
See Also
SaveTemplate Statement
Reference
341
PeriodCheck Function
Description
Verify whether or not a period string in YYYYPP format represents a valid fiscal
period.
Syntax
RetVal = PeriodCheck(PeriodString)
Remarks
The PeriodCheck function uses the following arguments:
Argument
Type
Description
RetVal
Integer
PeriodString
String
342
PeriodMinusPeriod Function
Description
Return the number of periods between two fiscal periods.
Syntax
NbrPeriods = PeriodMinusPeriod(PerNbr1, PerNbr2)
Remarks
The PeriodMinusPeriod function uses the following arguments:
Argument
Type
Description
NbrPeriods
Integer
PerNbr1
String
PerNbr2
String
Note: This function will use the number of periods in a fiscal year, as specified in the
GLSetup record, in order to derive an accurate result.
See Also
PeriodPlusPerNum Function
Reference
343
PeriodPlusPerNum Function
Description
Add a designated number of periods to an existing fiscal period.
Syntax
ResultingPerNbr = PeriodPlusPerNum(CurrPerNbr, NbrPeriodsToAdd)
Remarks
The PeriodPlusPerNum function uses the following arguments:
Argument
Type
Description
ResultingPerNbr
String
CurrPerNbr
String
NbrPeriodsToAdd
Integer
Note: This function will use the number of periods in a fiscal year, as specified in the
GLSetup record, in order to derive an accurate result.
See Also
PeriodMinusPeriod Function
344
PVChk Function
Description
Perform possible value error checking for the designated control.
Syntax
RetVal = PVChk(Ctrl, Cursor, SQLParmValue)
Remarks
PvChk performs error checking on the specified control using the stored procedure or
SQL text defined in the PV property of the control. The cursor is allocated if
uninitialized.
The difference between this function and the PVChkFetch functions is that this
function will not return the record to the application for display.
The PVChk function uses the following arguments:
Argument
Type
Description
RetVal
Integer
Ctrl
Control
Cursor
Integer
SQLParmValue
String
See Also
SAFMaskedText Control, PVChkFetch Functions, PV Property
Reference
345
PVChkFetch Functions
Description
Retrieve a composite record from the database using a SQL statement from the PV
property of an SAFMaskedText control.
Syntax
RetVal = PVChkFetch1(Ctrl, Cursor, SQLParmValue, bTable1, bTable1Length)
RetVal = PVChkFetch4(Ctrl, Cursor, SQLParmValue, bTable1, bTable1Length,
bTable2, bTable2Length, bTable3, bTable3Length, bTable4, bTable4Length)
RetVal = PVChkFetch8(Ctrl, Cursor, SQLParmValue, bTable1, bTable1Length,
bTable2, bTable2Length, bTable3, bTable3Length, bTable4, bTable4Length, bTable5,
bTable5Length, bTable6, bTable6Length, bTable7, bTable7Length, bTable8,
bTable8Length)
Remarks
Each SAFMaskedText control has a PV property which can contain a SQL statement
or stored procedure name. These functions can be used to fetch a composite record
instance based on the SQL text from the PV property of the control specified in the
Ctrl parameter. These functions are not applicable if the PV property does not contain
either a SQL statement or stored procedure name.
PVChkFetch1 is designed for SQL statements returning data from a single table. For
more advanced SQL statements having one or more table joins either PVChkFetch4 or
PVChkFetch8 can be used.
The PVChkFetch1 function uses the following arguments (PVChkFetch4 and
PVChkFetch8 respectively have four and eight table structures and corresponding
lengths. PNULL should be passed for unused table structure parameters as well as a
corresponding length of zero such as PNULL, 0)
Argument
Type
Description
RetVal
Integer
Ctrl
Control
Cursor
Integer
SQLParmValue
String
bTable1
346
Argument
Type
Description
bTable1Length
Integer
See Also
DBNavFetch Functions, PVChk Function, SAFMaskedText Control, PV Property
Example
The following example illustrates the usage of PVChkFetch1 in the Chk event of a
Payroll Work Location ID control. Since PNULL is passed for the control parameter
the SQL statement in the PV property of the cWrkLocId control itself is used. The ID
entered by the user is passed to the Chk event as chkstrg. By sending this value to
PVChkFetch1 it will be used as the last parameter to the restriction clause of the PV
SQL statement.
Sub cWrkLocId_Chk (chkstrg As String, retval As Integer)
Dim WorkLocation_Fetch
As Integer
RetVal = NoAction
End Sub
Reference
347
SaveTemplate Statement
Description
Save information from the current application to a designated template.
Syntax
Call SaveTemplate(TemplateID, Description, AppliesToUserID, IncludeLowerLevels,
StartingLevelNbr)
Remarks
The Solomon Template feature makes it possible to store data from the current screen
and subsequently paste that data into the same screen at a later time. These timesaving
templates can be saved to the database programmatically using the SaveTemplate
statement as well as via the Template menu item on the Edit menu. Each template can
contain complete transactions and entities or individual fields selected by the user.
Relative date and period features allow a template to paste data relative to the current
date and fiscal period. Templates can be designated as private to a specific user or
marked public for availability to all users. Templates are stored in the system database
and therefore they are independent of any particular application database.
Unless otherwise specified, all date and period values pasted from a template will be
equal to the Solomon business date, located on the File menu, and the current period
for the module. To override this default action, the user entering data for the template
must specify a new relative date or period value for each desired field. This is done
immediately before saving a template. Specifying a relative date or period value for a
field contained in grid detail lines will change the template value of that field for all
detail lines. Relative values can be defined by selecting the pertinent date or period
field and pressing F2 to start the Relative Date or Relative Period screen - whichever is
appropriate.
The SaveTemplate statement uses the following arguments:
Argument
Type
Description
TemplateID
String
Description
String
AppliesToUserID
String
IncludeLowerLevels
Integer
348
Argument
Type
Description
StartingLevelNbr
Integer
See Also
PasteTemplate Function
Reference
349
ScreenExit Statement
Description
Terminate the dynamic link with the Solomon Parent, log out of the database and
terminate the application.
Syntax
Call ScreenExit(OpCode, ParmStr)
Remarks
The ScreenExit call is required in the Unload event of Form1 for all applications
developed with Tools for Visual Basic.
The ScreenExit statement uses the following arguments:
Argument
Type
Description
OpCode
String
ParmStr
String
See Also
ApplInit Statement, ScreenInit Statement
350
ScreenInit Statement
Description
Perform all screen resource initializations that must occur after a dynamic link with the
Solomon Parent has been established and relevant resources have been allocated by the
application.
Syntax
Call ScreenInit
Remarks
The ScreenInit call is required in all applications developed with Tools for Visual
Basic.
Similar to the ApplInit statement, the ScreenInit statement initializes application
resources. However, the initializations occurring during ScreenInit are much more
extensive. For example, it is during this call that customizations are loaded, triggers are
set up, access rights are checked, an implied NEW operation is fired as well as many
other common initialization tasks.
Since database I/O occurs during the ScreenInit call, it must be called after ApplInit.
Additionally, it is required that the ScreenInit call occur after all SetAddr and
SqlCursor calls have been made for each level corresponding to the Levels property of
the SAFUpdate control.
See Also
ApplInit Statement, ScreenExit Statement, SetAddr Statement, SqlCursor
Statement, SAFUpdate Control
Reference
351
Example
The following code illustrates the basic order of calls that are made from within the
Form_Load event of Form1. Some of the calls are optional depending on the
requirements of a particular application but the ScreenInit call is always required.
Sub Form_Load ()
'Load application sub-form(s)
'Call LoadForm( SubFormName)
'SetAddr call(s)
'Call SetAddr(LEVEL0, "bTableName", bTableName, nTableName,
LenB(bTableName))
'SqlCursor call(s)
'Call SqlCursor(CSR_TableName, LEVEL0)
End Sub
352
SDelete Statement
Description
Delete the current record from a designated table within an existing SQL view.
Syntax
Call SDelete(Cursor, TablesDeletingFrom)
Remarks
A value of *.* can be passed as a table name, meaning that all current records in the
existing view will be deleted. Please note that this call requires that the current record
already be fetched via such functions as SqlFetch1 or SFetch1 so that the designated
cursor actually has a current record.
The SDelete statement uses the following arguments:
Argument
Type
Description
Cursor
Integer
TablesDeletingFrom
String
See Also
SDeleteAll Function, SFetch Functions, SqlFetch Functions
Reference
353
SDeleteAll Function
Description
Delete all records from the designated table(s) within a predefined view.
Syntax
RetVal = SDeleteAll(Cursor, TablesDeletingFrom)
Remarks
Deletes records from some or all of the tables in a view based on the current
restrictions. A view must have already been initialized for the specified cursor via
functions such as SQL, SFetch1 or SqlFetch4. If no restriction is specified when the
cursor is initialized, then this call will remove all records from the designated table(s)
in the view.
The SDeleteAll function uses the following arguments:
Argument
Type
Description
RetVal
Integer
Cursor
Integer
TablesDeletingFrom
String
See Also
SDelete Statement, SFetch Functions, SQL Statement, SqlFetch Functions
Example
Delete all vendors having a zero balance.
Dim SqlStr
As String
354
SetAddr Statement
Description
Associate a table name together with a VB variable and an optional screen level
number.
Syntax
Call SetAddr(LevelNbr, TableNameStr, bTableName, nTableName,
bTableNameLength)
Remarks
The SetAddr statement facilitates proper runtime binding between a VB data variable
and relevant data entry controls - including controls created using the Customization
Manager.
Although SWIM has access to extensive information about any particular data entry
control, one vital piece of information cannot be determined merely by looking at the
control itself. In particular, SWIM needs to know where the data for the control is
stored in memory. Since the data is actually stored in an underlying VB variable,
SWIM has no means of directly determining where that VB variable is stored in
memory. The SetAddr statement is used by the application to resolve this problem.
To facilitate the explanation of the linkage between the SetAddr statement and
corresponding data entry controls, consider the following user-defined datatype and a
corresponding SetAddr call for the Account database table:
Type Account
Acct
As String *
Active
As Integer
10
ConsolAcct
As String *
10
CuryId
As String *
Descr
As String *
30
NoteID
As Long
RatioGrp
As String *
SummPost
As String *
Type
As String *
User1
As String *
30
User2
As String *
30
User3
As Double
User4
As Double
End Type
Global bVBVarAccount As Account, nVBVarAccount As Account
Call SetAddr(LEVEL0, "bAccount", bVBVarAccount, nVBVarAccount,
LenB(bVBVarAccount))
Reference
355
The SetAddr call itself associates the value of the TableNameStr argument together
with the memory location of the first byte of the VB variable passed via the
bTableName argument. If the relevant table is a database table, SWIM can access
detailed information relating to each individual field contained therein using the SQL
data dictionary. For example, SWIM can determine the name, data type, maximum size
as well as the relative placement (e.g., byte offset) of each individual field within the
table. After the SetAddr call in the above example, SWIM would know that the first
byte of bVBVarAccount is at a particular location in memory, hereafter referred to as
location M, and furthermore that the first byte of bVBVarAccount.Acct is offset zero
bytes from location M as well as the fact that Acct is ten bytes long. Similarly, it would
also know that the first byte of bVBVarAccount.Active is offset ten bytes from
location M, and is two bytes long since it is an integer. Since the value of bAccount
is passed as the TableNameStr argument it is the string literal associated with memory
location M. Anytime SWIM encounters bAccount.<SomeFieldName> in a
FieldName property it will have all of this detailed information readily available so it
can access the corresponding data at the appropriate memory location. The same
concept applies when SWIM encounters bAccount.<SomeFieldName> in any of the
DBNav, Default, PV or Trigger properties.
As previously mentioned, the detailed information acquired by SWIM as a result of the
SetAddr call can be directly linked to the FieldName property of data entry controls.
The FieldName property contains a Struct.FieldName value along with other more
detailed information such as field offset value, declare type and length. Once they have
been fully initialized, these values facilitate the linkage between the control and the
associated memory location where the data value of the control is stored. In the vast
majority of cases the detailed field information is initialized automatically by SWIM in
using information acquired via a corresponding SetAddr call and the SQL data
dictionary. Usage of an unbound control is the only case where the developer must fill
in the detailed field information manually since it will not exist in the SQL data
dictionary.
The Struct.FieldName portion of the FieldName property must always be populated
with a string value in the bTableName.FieldName format. Using the above example,
a control for the Acct field would have a value of bAccount.Acct for the
Struct.FieldName portion of its FieldName property. Similarly the Active control
would have a value of bAccount.Active for the Struct.FieldName portion of its
FieldName property.
The first portion of this Struct.FieldName string, bAccount in our example, is used to
link the control with a particular SetAddr call that had the same value for its
TableNameStr argument. Once that initial linkage is made the exact memory location
can be determined automatically by correlating the last portion of the Struct.FieldName
string, Acct or Active in our example, with the detailed field information acquired
as a result of the relevant SetAddr call.
Thus, in general the SetAddr call facilitates the linkage of a
bTableName.FieldName type of string literal with a precise location in memory for
the corresponding data value.
356
Type
Description
LevelNbr
Integer
TableNameStr
String
bTableName
User-defined
datatype
nTableName
User-defined
datatype
bTableNameLength
Integer
Length (e.g., Size) of the entire bTableName userdefined type such as LenB(bTableName). Note: It is
critical to use LenB() instead of Len() for all nonnull table length parameters.
See Also
FieldName Property, SAFUpdate Control
Reference
357
Example
The following example illustrates how to perform SetAddr calls for a moderately
complex screen containing multiple levels such as the Payroll Employee Maintenance
screen. Notice that some of the SetAddr calls use the NOLEVEL flag - indicating that
these tables either do not have any corresponding data entry controls or that these
tables are merely not the master table for any level. In any case, detailed field level
information will be stored for each of these tables. Additionally, the null structure for
each of the tables will still be properly initialized.
Sub Form_Load ()
Call LoadForm(F0225001)
'Timesheet Defaults
Call LoadForm(F0225002)
'Miscellaneous Info
Call LoadForm(F0225003)
'Pay Information
Call LoadForm(F0225004)
'Employee Deductions
Call LoadForm(F0225005)
'Employee Benefits
Call ApplInit
Call SetAddr(LEVEL0, "bEmployee", bEmployee, nEmployee, LenB(bEmployee))
Call SetAddr(LEVEL1, "bWorkLoc", bWorkLoc, nWorkLoc, LenB(bWorkLoc))
Call SetAddr(LEVEL2, "bEarnType", bEarnType, nEarnType, LenB(bEarnType))
Call SetAddr(LEVEL3, "bPayGroup", bPayGroup, nPayGroup, LenB(bPayGroup))
Call SetAddr(LEVEL4, "bEarnDed", bEarnDed, nEarnDed, LenB(bEarnDed))
Call SetAddr(LEVEL5, "bBenEmp", bBenEmp, nBenEmp, LenB(bBenEmp))
Call SetAddr(NOLEVEL, "bPRDoc", bPRDoc, nPRDoc, LenB(bPRDoc))
Call SetAddr(NOLEVEL, "bPRSetup", bPRSetup, nPRSetup, LenB(bPRSetup))
Call SetAddr(NOLEVEL, "bPRTran", bPRTran, nPRTran, LenB(bPRTran))
Call SetAddr(NOLEVEL, "bDeduction", bDeduction, nDeduction,
LenB(bDeduction))
Call SetAddr(NOLEVEL, "bBenefit", bBenefit, nBenefit, LenB(bBenefit))
358
'Employee
Normal Level
'WorkLoc
Lookup Level
'EarnType
Lookup Level
'PayGroup
Lookup Level
'EarnDed
Detail Level
'BenEmp
Detail Level
Reference
359
SetAutoNbrFlag Statement
Description
Toggle the auto-numbering feature on and off.
Syntax
Call SetAutoNbrFlag(Control, ActiveFlag)
Remarks
This statement is used in cases where a data entry field may control the use of auto
numbering.
The SetAutoNbrFlag statement uses the following arguments:
Argument
Type
Description
Control
Control
ActiveFlag
Integer
See Also
AutoNbrDefault Function
Example
Sub cmodule_Chk (chkstrg As String, RetVal As Integer)
End Sub
360
SetButton Statement
Description
Toggle the Enabled property of Solomon parent toolbar buttons.
Syntax
Call SetButton(ToolBarButton, LevelNbr, EnabledPropVal)
Remarks
Usage of the SetButton statement allows the application to turn Solomon toolbar
buttons on and off.
Calls to SetButton cannot be made prior to the ApplInit call in the Form1_Load
event.
The SetButton statement uses the following arguments:
Argument
Type
Description
ToolBarButton
Integer
LevelNbr
Integer
EnabledPropVal
Integer
See Also
DisplayMode Statement
Reference
361
Example
The Release Payroll Batches process screen contains an SAFGrid control which
automatically displays all Payroll batches that are ready to be released. The SAFGrid
control only exists to facilitate the users need to specify which batches should be
released. Consequently, for example, the Insert and Save buttons on the Solomon
toolbar do not need to be enabled since the user is not allowed insert new batches nor
update existing batches.
The following code is used to disable Solomon toolbar buttons that the user should not
be allowed to press while the Release Payroll Batches application has focus.
'Disable buttons so user will not be able to take any action on batches
'in the grid
Call SetButton(DeleteButton + InsertButton + SaveButton + CancelButton,
AllLevels, False)
'Re-enable the control used to Select/Deselect batches.
Call MSetProp(cCurrBatSelected, PROP_ENABLED, True)
362
SetDefaults Statement
Description
Set one or more controls to their default value using either their Default Property or
Default Event code.
Syntax
Call SetDefaults(Form, FirstControl, LastControl)
Remarks
Each Tools for Visual Basic data control has both a Default property as well as a
Default event. Any particular data control can use one of these two methods to define a
default data value for itself. The system uses these methods any time a particular
control is to be initialized to its default value. An exhaustive discussion of all the times
when this occurs is beyond the scope of the SetDefaults statement. However, one such
time a control is set to its default value is when the application explicitly directs the
system to do so via usage of the SetDefaults statement in reference to the relevant
control.
The SetDefaults statement can be used to default a range of controls based on their
TabIndex property order. All controls whose TabIndex falls between FirstControl and
LastControl will be defaulted. The Level_SetDefaults statement is functionally
equivalent except it can be used to explicitly default all controls having a particular
level number in their Level property.
Since SetDefaults implies a change in the data value of the designated controls, the
system will mark the controls as requiring error checking. The system does not,
however, immediately perform the requisite error checking (e.g., it does not
immediately fire the Chk event). The error checking is nevertheless guaranteed to
occur prior to any updates to the database.
Note: When an application needs to null out a particular field, perhaps because the field
is no longer applicable, it should explicitly do so programmatically and then redisplay
the relevant control using the DispField statement. After the control has been
redisplayed it can then be disabled using the SetProps statement. The SetDefaults
statement should not be used in these cases even if the relevant control has no Default
Property value and no code within Default Event. A developer may well wonder why
this caution would be expressed since the field will in fact be nulled out when no
Default Property or Event code exists and therefore the application will appear to work
properly during testing. However, developers must always be conscious of the fact that
the end user may subsequently apply a customization which among other things
defines some default value other than null for the relevant control. Such a
customization would reveal a subtle flaw in the underlying application with regards to
its usage of the SetDefaults statement to null out a particular data field.
Reference
363
The following code conceptually illustrates how to properly null out and disable a
control which is no longer applicable:
Record.Field = NULL (0 for numeric datatypes , "" for string datatype)
Call DispField(cField)
Call SetProps(Form1, cField, cField, Enabled, False)
Type
Description
Form
Control
FirstControl
Control
LastControl
Control
See Also
Default Event, Default Property, DispField Statements, Level_SetDefaults
Statement, SetProps Statement
364
SetKeysEnabledOnly Statement
Description
Enable/Disable non-keyfield Tools for Visual Basic custom controls.
Syntax
Call SetKeysEnabledOnly(Form, FirstControl, LastControl, Action)
Remarks
The SetKeysEnabledOnly statement uses the following arguments:
Argument
Type
Description
Form
Control
FirstControl
Control
LastControl
Control
Action
Integer
See Also
DisplayMode Statement, SetProps Statement
Reference
365
SetLevelChg Statement
Description
Set the update status of a specific level.
Syntax
Call SetLevelChg(LevelNbr, Status)
Remarks
Each update level, as defined by the Levels property of the SAFUpdate control, has a
corresponding level status flag that is automatically maintained by the system. The
purpose of the level status flag is to facilitate the optimization of database updates
performed in response to Parent toolbar buttons. In general, these flags allow the
system to only perform database updates for update levels which have in fact changed.
If no information has changed then no information needs to be saved.
As previously mentioned, these update flags are automatically maintained by the
system. When an existing record is loaded the flag is set to NOTCHANGED. If any
non-keyfield is subsequently modified then the level status flag for the corresponding
level is set to UPDATED. When a new record is being entered, the level status flag is
set to INSERTED.
The SetLevelChg statement allows the application to override the current value a the
status flag for a particular level. This can be useful if a data value is modified
programmatically and therefore the system needs to be notified that something has
changed so the corresponding information will actually be saved when the user presses
the Save toolbar button.
The SetLevelChg statement uses the following arguments:
Argument
Type
Description
LevelNbr
Integer
Status
Integer
See Also
TestLevelChg Function
366
Example
The Payroll Earnings Type Maintenance screen contains a button to automatically
populate the grid with all Deductions. This amounts to inserting records into the grid
(e.g., into its underlying memory array) under program control. Since the data is not
entered via the user interface by the user, the system needs to be notified that
information at the grid level (e.g., LEVEL1 in this case) has been programmatically
updated and therefore needs to be saved. However, such notification only needs to
occur if the system is not already aware that data has changed.
'If any records were inserted into the memory array then we need to make
'sure that the level status for the detail level is something other than
'NOTCHANGED so the system will know that something needs to be saved.
If (AnyRecsInserted = True) Then
If (TestLevelChg(LEVEL1) = NOTCHANGED) Then
Call SetLevelChg(LEVEL1, UPDATED)
End If
End If
Reference
367
SetProps Statement
Description
Set the value of a particular property for the designated control(s).
Syntax
Call SetProps(Form, FirstControl, LastControl, PropertyName, NewPropValue)
Remarks
To set new property values for controls, the SetProps statement should be used rather
than modifying the properties directly in VB code. Usage of SetProps allows the
system to track changes to property values so as to avoid conflicts with customizations
and / or other APIs such as the DisplayMode statement.
For example, assume FieldA is disabled directly by the application using the
FieldA.Enabled = False methodology. Since this property modification is made directly
using VB code as opposed to the SetProps statement, the system has no knowledge of
the fact that FieldA is now disabled. This can cause conflicts with the Customization
Manager since some types of customizations do not apply to controls that the
underlying application has disabled. The same is true for other properties as well.
Furthermore by setting properties directly, the effectiveness of statements such as
DisplayMode is eliminated. Once DisplayMode has been called, all calls to SetProps
referencing the Enabled property, are essentially ignored. The advantage of this type of
architecture is that it reduces code complexity. In particular, the application can issue
calls to the SetProps statement without surrounding each and every call with a
conditional statement (such as If DisplayMode = False).
The SetProps statement uses the following arguments:
Argument
Type
Description
Form
Control
FirstControl
Control
LastControl
Control
PropertyName
String
NewPropValue
String or Integer
368
Valid Datatype
PROP_BLANKERR (required)
Integer
TRUE / FALSE
PROP_CAPTION
String
PROP_CUSTLIST
String
PROP_ENABLED
Integer
PROP_HEADING
String
PROP_MASK
String
PROP_MIN
String
PROP_MAX
String
PROP_TABSTOP
Integer
TRUE / FALSE
PROP_VISIBLE
Integer
TRUE / FALSE
TRUE / FALSE
See Also
BlankErr Property, DisplayMode Statement, DisplayModeSetProps Statement,
Enabled Property, Heading Property, Mask Property, Min Property, Max
Property, MSetProp Statement, TabStop Property, Visible Property
Example
The Payroll Deduction Maintenance screen allows deductions to be based on one of
several different values such as earnings or even another deduction. If a DeductionA is
based on another DeductionB then DeductionB must be entered by the user in the Base
Deduction ID field. However, in all other cases the Base Deduction ID field is not
applicable and therefore should be disabled.
The following code is used to modify the BlankErr and Enabled properties of the Base
Deduction ID control.
If (bDeduction.BaseType = "D") Then
'Current deduction IS based on another deduction.
Call SetProps(Form1, Form1.cBaseid, Form1.cBaseid, "Enabled", True)
Call SetProps(Form1, Form1.cBaseid, Form1.cBaseid, "BlankErr", True)
Else
'Current deduction is NOT based on another deduction.
Call SetProps(Form1, Form1.cBaseid, Form1.cBaseid, PROP_ENABLED, False)
Call SetProps(Form1, Form1.cBaseid, Form1.cBaseid, PROP_BLANKERR, False)
End If
Reference
369
SetRestart Statement
Description
Identify the single cursor used to loop through multiple sets of high-level data items,
within the context of a process, each one of which is autonomous and therefore is
processed in a separate transaction.
Syntax
Call SetRestart(Cursor)
Remarks
In the context of Solomon, a process is an application that performs a logical set of
operations on one or more sets of data in order to transform each data set from one
business stage to another without user interaction. Thus at a conceptual level, a process
transforms one set of data and then begins the same transformation on another set of
data which is completely independent of the first set of data.
For example, consider the General Ledger Posting process. This process loops through
Batch records, each of which is completely independent of all other Batch records, and
posts the General Ledger transactions associated with each individual Batch.
Since a process operates on data it must therefore also be able gracefully manage faulty
data. In order for a process to be fault tolerant it will need not only the ability to write
error messages to a log but it will also have to abort database updates which occurred
prior to the error in order to preserve the logical integrity of the database. After an error
has been properly managed, the process will need to either move on to the next set of
data to be processed or as a last resort the process itself may need to be terminated.
When errors of various sorts occur, such as when a particular referential record cant
be found or an out of balance condition is detected, the Status statement can be used to
report the precise nature of the fatal error to the Event Log. Fatal errors that occur on
the restart cursor itself, such as an I/O error or a corrupt stored procedure will cause the
application to terminate since by definition it cannot even process the next record in its
outermost processing loop. Fortunately, fatal errors on the restart cursor itself are
extremely rare. All other fatal cause the system to automatically go into abort mode.
Abort mode can simply be defined as a mode in which the system is essentially
ignoring all database calls since the current transaction is going to be aborted anyway
(as opposed to successfully committed). For example, if the current Batch cannot be
posted for some reason then report the problem and move on to the next Batch. Abort
mode is basically a method whereby the system makes it easier for the application to
move on to the next autonomous set of data (e.g., Batch in this case). In these cases,
code complexity is reduced since the application does not have to surround each
database call with conditional statements which are conceptually equivalent to If
(EverythingOK = True) Then .... As previously stated this is due to the fact that
database calls are essentially ignored as long as the application is in abort mode.
Nevertheless this leads directly to the question relating to the precise point at which the
application comes back out of abort mode.
370
Type
Description
Cursor
Integer
See Also
Status Statement, TranBeg Statement, TranEnd Statement
Example
The following code snippet from the General Ledger Posting process illustrates how a
restart cursor on the Batch cursor is implemented using the SetRestart statement.
.
.
.
Call SetRestart(Post_CSR_Batch)
Call TranBeg(True)
BatchFetch = SqlFetch1(Post_CSR_Batch, SqlStr, bBatch, LenB(bBatch))
While (BatchFetch = 0)
Call Status(SaveGoodArgVals, False, Trim$(PostControlInfo.
Module_Caption) + SParm(bBatch.Module) + NL +
Trim$(PostControlInfo.Batch_Caption) +
SParm(bBatch.BatNbr), DISP_ONLY)
'Initialize all of the BatchFiscal* structures.
'before the call to IsBatchOKToPost().
Call InitAllBatchFiscals
OkToPost = IsBatchOkToPost(MsgNbr)
Reference
371
372
Reference
373
SetStatusBarText
Description
Sets the text to appear in the text pane of the status bar and, optionally, the tooltip text
to be displayed for the status bar text. If no tooltip text is specified, the tooltip displays
the same text as the status bar text.
Syntax
Call SetStatusBarText(Text, Tooltip)
Remarks
The SetStatusBarText statement uses the following arguments:
Argument
Type
Description
Text
String
Tooltip
String
Example
This example displays in the status bar the quantity available of an inventory item.
Notice for the text of the message, the code uses a message from messages.csv so it can
easily be translated to any language.
QtyAvail = gADGPlan.GetQtyAvailToday(pInvtID, pSiteID)
'Inventory Item %s has a quantity of %s available
msg = GetMessageText(15376, Trim$(pInvtID), Format$(QtyAvail))
Call SetStatusBar(msg, "")
374
SetSWIMPrintInfo Function
Description
Replace the current print information and settings with those in the applications PInfo
structure.
Syntax
result = SetSWIMPrintInfo( printInfo )
Remarks
The SetSWIMPrintInfo function uses the following arguments:
Argument
Type
Description
Result
Boolean
printInfo
PInfo
See Also
GetSWIMDefaultPrintInfo Function, GetSWIMPrintInfo Function, PInfo
structure
SetTI_Alias_Level Statement
Description
Sets a different level for a control for use during processing by transaction import.
Syntax
Call SetTI_Alias_Level(Control, Level)
Remarks
This function is used to specify a different level for a control when importing data with
transaction import. It is used when it is necessary for transaction import to process the
control at a different level than the level specified in the controls Level property.
The SetTI_Alias_Level statement uses the following arguments:
Argument
Type
Description
Control
Control
Level
Integer
Reference
375
SFetch Functions
Description
Used to retrieve a composite record from the database based on some pre-defined SQL
statement or stored procedure.
Syntax
RetVal = SFetch1(Cursor, bTable1, bTable1Length)
RetVal = SFetch4(Cursor, bTable1, bTable1Length, bTable2, bTable2Length,
bTable3, bTable3Length, bTable4, bTable4Length)
RetVal = SFetch8(Cursor, bTable1, bTable1Length, bTable2, bTable2Length,
bTable3, bTable3Length, bTable4, bTable4Length, bTable5, bTable5Length, bTable6,
bTable6Length, bTable7, bTable7Length, bTable8, bTable8Length)
Remarks
In order to fetch information from the server it must first know what tables, records and
fields are being queried from a particular cursor. Consequently the cursor must first be
initialized with either a SQL statement or stored procedure via the use of the Sql
statement or the SqlFetch1, SqlFetch4 or SqlFetch8 functions. Once the database
view has been established these functions will retrieve the next sequential record in the
view consistent with the Order By clause of the SQL statement used to initialize the
view. After the last record in the view has been returned all subsequent calls to
SFetch1, SFetch4 and SFetch8 will return NOTFOUND.
SFetch1 is designed for SQL statements returning data from a single table. For more
advanced SQL statements having one or more table joins either SFetch4 or SFetch8
can be used.
The SFetch1 function uses the following arguments (SFetch4 and SFetch8
respectively have four and eight table structures and corresponding lengths. PNULL
should be passed for unused table structure parameters as well as a corresponding
length of zero such as PNULL, 0)
Argument
Type
Description
RetVal
Integer
Cursor
Integer
bTable1
bTable1Length
Integer
376
DISTINCT keyword
GROUP BY clause
HAVING clause
Subqueries
See Also
Sql Statement, SqlFetch Functions, SGroupFetch Functions
Example
The following code reads through all records in the Account table. Since the
Account_All stored procedure only selects data from a single table (e.g., the Account
table) SFetch1 would be adequate. However in this example, SFetch4 is actually used
to illustrate how to pass PNULL,0 for unused table structure arguments.
Dim
CSR_Account
Dim
SqlStr
Dim
AcctFetch
As Integer
As String
As Integer
'Allocate cursor
Call SqlCursor( CSR_Account, NOLEVEL)
'Initialize cursor with SQL stored procedure and fetch first record
SqlStr = "Account_All" + sparm(SQLWILDSTRING)
AcctFetch = SqlFetch4(CSR_Account, SqlStr, bAccount, LenB(bAccount),
PNULL, 0, PNULL, 0, PNULL, 0)
'Read through all Account records
While (AcctFetch = 0)
AcctFetch = SFetch4(CSR_Account, bAccount, LenB(bAccount),
PNULL, 0, PNULL, 0, PNULL, 0)
Wend
Reference
377
SGroupFetch Functions
Description
Used to retrieve a composite record from the database based on some pre-defined SQL
statement or stored procedure containing one or more group aggregate functions and/or
clauses.
Syntax
RetVal = SGroupFetch1(Cursor, bTable1, bTable1Length)
RetVal = SGroupFetch4(Cursor, bTable1, bTable1Length, bTable2, bTable2Length,
bTable3, bTable3Length, bTable4, bTable4Length)
RetVal = SGroupFetch8(Cursor, bTable1, bTable1Length, bTable2, bTable2Length,
bTable3, bTable3Length, bTable4, bTable4Length, bTable5, bTable5Length, bTable6,
bTable6Length, bTable7, bTable7Length, bTable8, bTable8Length)
Remarks
In order to fetch information from the server it must first know what tables, records and
fields are being queried from a particular cursor. Consequently the cursor must first be
initialized with either a SQL statement or stored procedure via the use of the Sql
statement. SGroupFetch1, SGroupFetch4 or SGroupFetch8 are only designed for
cases where the SQL statement used to initialize the cursor contains one or more of the
following:
DISTINCT keyword
GROUP BY clause
HAVING clause
Subqueries
The logically equivalent SFetch1, SFetch4 and SFetch8 functions should be used if
the SQL statement does not contain any of the above referenced items.
Once the database view has been established these functions will retrieve the next
sequential record or data value in the view consistent with the Order By or Group By
clause of the SQL statement used to initialize the view. After the last record or data
value in the view has been returned all subsequent calls to SGroupFetch1,
SGroupFetch4 and SGroupFetch8 will return NOTFOUND.
SGroupFetch1 is designed for SQL statements returning data from a single table. For
more advanced SQL statements having one or more table joins either SGroupFetch4
or SGroupFetch8 can be used.
378
Type
Description
RetVal
Integer
Cursor
Integer
bTable1
User-defined
datatype
bTable1Length
Integer
Note: The type and size of the data returned can vary when the SQL statement contains
one or more group aggregates. For the COUNT group aggregate, the data will always
be returned as a 4-byte integer (e.g., Long VB datatype). The MIN and MAX group
aggregates always return the same data type and length as the field on which the
aggregate is based. The SUM and AVG group aggregates always return 8-byte floating
point values (e.g., Double VB datatype).
See Also
Sql Statement, SFetch Functions
Example
This example calculates the sum of the POReceipt.RcptQtyTot in batch 000001 using
the SUM group aggregate and stores the result in a local variable called RetQtyTotal.
Note that the SUM is the data that is actually fetched and therefore it is stored in
RetQtyTotal rather than FetchRetVal.
Dim FetchRetVal
as Integer
Dim RetQtyTotal
As Double
'Initialize the cursor with a SQL statement containing the SUM group
'aggregate
Call sql(CSR_POReceipt, "Select SUM(RcptQtyTot) From POReceipt Where
POReceipt.BatNbr = '000001' Order By POReceipt.RcptNbr")
'Actually retrieve the SUM from the database server
FetchRetVal = SGroupFetch1(CSR_POReceipt, RetQtyTotal, LenB(RetQtyTotal))
Reference
379
SInsert Statements
Description
Insert one record into each specified table within an existing database view.
Syntax
Call SInsert1(Cursor, TablesInsertingInto, bTable1, bTable1Length)
Call SInsert4(Cursor, TablesInsertingInto, bTable1, bTable1Length, bTable2,
bTable2Length, bTable3, bTable3Length, bTable4, bTable4Length)
Call SInsert8(Cursor, TablesInsertingInto, bTable1, bTable1Length, bTable2,
bTable2Length, bTable3, bTable3Length, bTable4, bTable4Length, bTable5,
bTable5Length, bTable6, bTable6Length, bTable7, bTable7Length, bTable8,
bTable8Length)
Remarks
New records can be programmatically inserted directly into an existing database table
via the use of the SInsert1, SInsert4 and SInsert8 statements. In order to insert
information into the database, the server must first know what tables are being
referenced by a particular cursor. Consequently the cursor must first be initialized with
either a SQL statement or stored procedure via the use of the Sql statement or the
SqlFetch1, SqlFetch4 or SqlFetch8 functions. Once the database view has been
established these functions will insert one new record into each table referenced in the
TablesInsertingInto argument using data from corresponding table structure arguments.
SInsert1 is designed for SQL statements referencing a single table. In this case the
TablesInsertingInto is always the name of the single table actually referenced. For
more advanced SQL statements having one or more table joins either SInsert4 or
SInsert8 can be used. The referencing of more than one table does not automatically
force the insertion of a record into every table in the view anytime SInsert4 or
SInsert8 is used on the corresponding cursor. A single record will only be inserted into
each table explicitly specified in the TablesInsertingInto argument so long as each
table name so specified is also referenced in the SQL statement which was used to
initialize the current view. Thus, for example, if TableA and TableB are the only two
tables referenced in the SQL statement used to initialize the current view then a value
of TableXYZ would be invalid for the TablesInsertingInto argument.
380
Type
Description
Cursor
Integer
TablesInsertingInto
String
bTable1
User-defined
datatype
bTable1Length
Integer
See Also
Sql Statement, SqlFetch Functions
Example
This example illustrates the usage of SInsert1 to insert a copy of each record in the
Account table into a table called AccountCopy. The AccountCopy table does not exist
in a standard Solomon application database. Nevertheless to facilitate this example it is
assumed that a table named AccountCopy does in fact exist in the application database
and that it also has the exact same field and index characteristics as the Account table.
Dim CSR_Account
As Integer
Dim CSR_AccountCopy_Insert
As Integer
Dim SqlStr
As String
Dim AcctFetch
As Integer
Reference
381
382
SParm Function
Description
Convert a string into a SQL parameter string.
Syntax
SQLParmStr = SParm(StrToConvert)
Remarks
The SParm function uses the following arguments:
Argument
Type
Description
SQLParmStr
String
StrToConvert
String
See Also
DParm Function, FParm Function, IParm Function
Example
These examples assume the following SQL statement was used to create a stored
procedure called Employee_EmpId
Select * from Employee where EmpId LIKE @parm1 order by EmpId
This code snippet illustrates how to use the Employee_EmpId stored procedure to fetch
the employee record for employee #000581.
SqlStr = "Employee_EmpId" + SParm("000581")
Employee_Fetch = SqlFetch1(CSR_Employee, SqlStr, bEmployee, LenB(bEmployee))
This code snippet illustrates how to use the Employee_EmpId stored procedure to fetch
all employee records by using a wildcard value for the EmpId parameter.
SqlStr = "Employee_EmpId" + SParm(SQLWILDSTRING)
Employee_Fetch = SqlFetch1(CSR_Employee, SqlStr, bEmployee, LenB(bEmployee))
While ( Employee_Fetch = 0)
Employee_Fetch = SFetch1( CSR_Employee, bEmployee, LenB(bEmployee))
Wend
Reference
383
This code snippet illustrates how to use the Employee_EmpId stored procedure to fetch
all employee records beginning and ending with zero by using a combination of string
literals and single character wildcard values for the EmpId parameter.
SQLParmStr = "0" + SQLWILDCHAR + SQLWILDCHAR + SQLWILDCHAR + SQLWILDCHAR + "0"
SqlStr = "Employee_EmpId" + SParm(SQLParmStr)
Employee_Fetch = SqlFetch1(CSR_Employee, SqlStr, bEmployee, LenB(bEmployee))
While ( Employee_Fetch = 0)
Employee_Fetch = SFetch1( CSR_Employee, bEmployee, LenB(bEmployee))
Wend
384
Sql Statement
Description
Initialize a new database view.
Syntax
Call Sql(Cursor, SqlStr)
Remarks
Takes the specified SQL text, compiles it, and then executes it. If fetch operations are
required then one of the SFetch functions must be called. If the SQL statement is
performing an Update Set, Delete From or Insert Into operation, no subsequent fetch
operations are required. If the SQL statement references one or more parameters, the
SqlSubst and SqlExec functions must also be called.
The Sql statement uses the following arguments:
Argument
Type
Description
Cursor
Integer
SqlStr
String
See Also
SFetch Functions, SqlSubst Statement, SqlExec Statement, SqlFetch Functions
Example
Dim SqlStr
As String
Reference
385
SqlCursor Statement
Description
Allocate a new database cursor.
Syntax
Call SqlCursor(Cursor, Flags)
Remarks
All read/write communication between an application and the database must occur
through a database cursor. A cursor is basically a database resource used to track low
level information required to implement SQL database read/write operations. For
example, a cursor tracks the SQL statement used to initialize the current view, what
individual fields were selected, the current record within the view as well as other more
detailed information.
Each level within a screen must have a corresponding cursor allocated within the
Form_Load event of Form1 to facilitate database read/write activity at that level.
Additionally, many of the SQL API calls within Tools for Visual Basic, such as Sql,
SFetch1, SqlFetch1 and SUpdate1 require a database cursor as one of their
arguments.
Each application can allocate a maximum of 36 cursors. Cursors no longer needed by
the application can optionally be freed via the use of the SqlFree statement. All cursors
are automatically released by the system when the application terminates execution
(e.g., when ScreenExit is called).
The SqlCursor statement uses the following arguments:
Argument
Type
Description
Cursor
Integer
Flags
Integer
One or more special flags notating what and/or how the cursor
will be used. At a minimum the Flags parameter must contain
one of the LEVEL0 through LEVEL9 or NOLEVEL symbolic
constants defined in Applic.DH. Cursors not explicitly
associated with a particular level number should be allocated
using the NOLEVEL flag.
The following symbolic constants can optionally be passed as Flags (by adding them
to the required LEVEL0 through LEVEL9 or NOLEVEL symbolic constants):
386
See Also
SFetch Functions, SInsert Statements, Sql Statement, SqlFetch Functions, SqlFree
Statement, SUpdate Statements
Example
The following example illustrates how to allocate multiple cursors for a moderately
complex screen containing multiple levels such as the Payroll Employee Maintenance
screen. Notice that some of the cursors are allocated using the NOLEVEL flag indicating that these cursors are not explicitly reserved for database read/write activity
associated with any particular level on the screen.
Sub Form_Load ()
Call loadform(F0225001)
'Timesheet Defaults
Call loadform(F0225002)
'Miscellaneous Info
Call loadform(F0225003)
'Pay Information
Call loadform(F0225004)
'Employee Deductions
Call loadform(F0225005)
'Employee Benefits
Call ApplInit
Call SetAddr(LEVEL0, "bEmployee", bEmployee, nEmployee, LenB(bEmployee))
Call SetAddr(LEVEL1, "bWorkLoc", bWorkLoc, nWorkLoc, LenB(bWorkLoc))
Call SetAddr(LEVEL2, "bEarnType", bEarnType, nEarnType, LenB(bEarnType))
Call SetAddr(LEVEL3, "bPayGroup", bPayGroup, nPayGroup, LenB(bPayGroup))
Call SetAddr(LEVEL4, "bEarnDed", bEarnDed, nEarnDed, LenB(bEarnDed))
Call SetAddr(LEVEL5, "bBenEmp", bBenEmp, nBenEmp, LenB(bBenEmp))
Call SetAddr(NOLEVEL, "bPRDoc", bPRDoc, nPRDoc, LenB(bPRDoc))
Call SetAddr(NOLEVEL, "bPRSetup", bPRSetup, nPRSetup, LenB(bPRSetup))
Call SetAddr(NOLEVEL, "bPRTran", bPRTran, nPRTran, LenB(bPRTran))
Call SetAddr(NOLEVEL, "bDeduction", bDeduction, nDeduction,
LenB(bDeduction))
Call SetAddr(NOLEVEL, "bBenefit", bBenefit, nBenefit, LenB(bBenefit))
'Allocate one cursor for each level on the screen
Call SqlCursor(CSR_Employee, LEVEL0)
'Employee
'WorkLoc
'EarnType
'PayGroup
'EarnDed
Normal Level
Lookup Level
Lookup Level
Lookup Level
Detail Level
Reference
Call SqlCursor(CSR_BenEmp_DBNav, LEVEL5)
'BenEmp
387
Detail Level
388
SqlCursorEx
Description
Allocate a new database cursor.
Syntax
Call SqlCursorEx(Cursor, Flags, CursorName, ReferencedTableNames,
UpdateTableNames)
Remarks
All read/write communication between an application and the database must occur
through a database cursor. A cursor is basically a database resource used to track low
level information required to implement SQL database read/write operations. For
example, a cursor tracks the SQL statement used to initialize the current view, what
individual fields were selected, the current record within the view as well as other more
detailed information.
Each level within a screen must have a corresponding cursor allocated within the
Form_Load event of Form1 to facilitate database read/write activity at that level.
Additionally, many of the SQL API calls within Tools for Visual Basic, such as Sql,
SFetch1, SqlFetch1 and SUpdate1 require a database cursor as one of their
arguments. If the cursor handle passed to one of these SQL API calls has not been
previously allocated then it will automatically be allocated during the call. However it
is important to be aware of the fact that all cursors not explicitly allocated, via a
SqlCursorEx call, are automatically allocated as read-only cursors.
Each application can allocate a maximum of 36 cursors. Cursors no longer needed by
the application can optionally be freed via the use of the SqlFree statement. All cursors
are automatically released by the system when the application terminates execution
(e.g., when ScreenExit is called).
The Solomon kernel supports the reuse of cursors. In the Microsoft SQL Server
environment, use SqlFree() to free a cursor and release the memory it used. In the
Scalable SQL or Pervasive.SQL environment, SqlFree() releases the cursor, but does
not release the memory used by the cursor until the database session is closed. This
behavior can cause out-of-memory conditions on some large screens. Therefore, use
SqlFree() in the Scalable SQL or Pervasive.SQL environment with care.
You should use SqlFree() on the same cursor for a different SQL statement because
SqlFree(): makes code more readable and logical; clears out the attributes associated
with the old cursor; forces attribute specification for the new cursor; releases any locks
associated with a cursor; and releases all memory allocated for the cursor.
If you do not use a SqlFree() call between Sql() calls using the same cursor, and each
Sql() call issues a different Sql statement, the attributes and table names specified in
the SqlCursorEx() call apply to all SQL statements issued with this cursor.
Every reuse of a cursor must be in the same database for which the SqlCursorEx() call
was issued. If SqlCursorEx() specifies the SqlSystemDb flag, then all database calls
made with this cursor are executed against the system database.
Reference
389
Type
Integer
Description
Variable to be initialized with a resource handle for
a SQL database cursor.
Flags
Integer
CursorName
String
ReferencedTableNames String
UpdateTableNames
String
390
SqlReadOnly - This flag indicates that the cursor is used exclusively for read
operations, not for record inserts, updates, or deletions. An error is generated if
you attempt an Supdate(), Sdelete(), or Sinsert() call on a cursor that contains this
flag. If a cursor is not explicitly declared by the application using either SqlCursor
or SqlCursorEx(), the Solomon kernel declares and allocates the cursor
automatically. The cursor automatically declared on Sql() or SqlFetch?() calls will
specify this flag if the operation is contained within a transaction (i.e., a TranBeg()
statement has been issued).
Rows fetched with this cursor type are not exclusively locked, regardless whether
they are fetched within a transaction. The shared database connection is used to
execute the operation associated with this cursor. If this is the only cursor flag
specified (other than the level identifier), the cursor API will use buffering to fetch
multiple records with one database call.
API Type: Advanced Cursor
Example Uses: A process that needs to accumulate the sum of a floating point
field and store the result in a different record; if the summing needs to take place
within a transaction, this flag is ideal.
SqlFastReadOnly - Like the SqlReadOnly flag, this flag indicates that the cursor is
used exclusively for read operations. All database operations occurring on this
type of cursor are serviced directly from Microsoft SQL Servers faster low-level
API. Cursors with this flag should not be used when accessing a table that may
have insert, update, or delete operations performed on it from a different cursor in
the same database transaction. The operation is executed using a connection that is
explicitly used for read-only operations. Therefore, records fetched with this
cursor type are not exclusively locked, regardless whether they are fetched within
a transaction.
API Type: Low-level
Example Uses: The application needs to load a display-only grid with values from
many General Ledger Transaction (GLTran) records.
Reference
391
SqlList - This flag indicates that read/write operations performed on the cursor are
automatically buffered to improve performance. If an application updates even one
row on a buffered cursor, it must update all rows read using that cursor within the
same database transaction; otherwise, a sparse update error occurs.
With buffering, as many records (or rows) are returned from the server as will fit
in 30K of memory space. Buffering is not available for the low-level API. The
Solomon kernel uses buffering as the default for all fetches that use the Advanced
Cursor API, thus greatly improving performance.
In the Microsoft SQL Server environment, all database operations are buffered
whenever possible, regardless whether this flag has been specified.
API Type: Advanced Cursor
Example Uses: There is no use for this flag in the Microsoft SQL Server
environment.
SqlNoSelect - This flag indicates that the SQL statement to be performed on the
cursor can be any valid Microsoft SQL Server statement except a Select statement.
No Sfetch(), Sinsert(), Supdate(), or Sdelete() calls can be performed on this
cursor. The most common use for this type of cursor is to process Update and
Delete Microsoft SQL Server statements. The Solomon kernel releases the dbproc
after execution of the SQL Server statement, to allow the Solomon kernel to use
the shared database connection to perform this operation.
All stored procedures that do not contain a Select statement should use a cursor
with this flag specified. Solomon IV 4.x Release and Posting processes use this
cursor flag.
API Type: Low-level
Example Uses: The application needs to issue a large stored procedure that
contains multiple update and select statements, as well as conditional logic or other
T-SQL logic.
392
SqlSingleRow - This flag is used with cursors that never process more than one
composite record after each Select statement. It is designed primarily to facilitate
optimization on the Microsoft SQL Server platform. All database operations
occurring on a SqlSingleRow cursor are serviced directly from Microsoft SQL
Servers faster low-level API.
SFetch calls on cursors of this type should not be separated from the associated Sql
call by any other database operations. The simplest method to satisfy this
requirement is to use the SqlFetch function. An application using this flag must
use the cursor immediately for single-row lookup or insertion so that the Solomon
kernel can release the dbproc.
When an application inserts a record instead of fetching one, the Sinsert() call
must immediately follow the Sql() call. Performing SqlFetch() followed by
Sinsert() is not supported. Instead, issue the Sql() call followed by the Sinsert()
call. Because of this requirement, the Solomon kernel can use the shared
database connection to perform this operation.
If an application attempts to specify this flag on a non-lookup level cursor, an error
is generated.
API Type: Low-level
Example Uses: The application needs to fetch the GLSetup record to get the
current period, but has no other use for it. As another example, an application
needs to insert one record, but do nothing else with that record.
SqlSystemDb - This flag indicates that all database operations for the specified
cursor are directed to the Solomon system database. By default, all database
operations for the cursor are performed on the Solomon application database.
When using this flag in addition to other cursor optimization flags, you can
separate the flags using + or |. For example, to declare a cursor for reading and
only reading the User table in the System database, the SqlCursorEx statement
would use the following syntax:
Note: For those optimization flags that invoke Microsoft SQL Servers low-level API
(SqlFastReadOnly, SqlNoSelect, and SqlSingleRow), database operations for the
cursor optimized with one of these flags on the SQL Server platform bypass the use of
SQL Servers advanced cursor API. As a result, database operations are serviced
directly from SQL Servers low-level API, thus resulting in enhanced performance.
However, when using this low-level API, the cursor can encounter contention with
other cursors in the same application. (This is not the case when all operations are
serviced by SQL Servers advanced cursor API.) SQL Server statements processed
with a cursor using the SqlFastReadOnly, SqlNoSelect, or SqlSingleRow flag must
include all fields for every table referenced by the SQL statement. For example,
partial-record Select statements (Select BatNbr from Batch as opposed to Select *
from Batch) are not supported by cursors allocated with these flags specified.
Reference
393
SqlErr Function
Description
Obtain the return value for the SQL operation last performed.
Syntax
RetVal = SqlErr()
Remarks
This function can be used after any SQL call that is declared as a statement (as opposed
to a function), in order to obtain the return value. For example, the call SInsert1 is
declared as a subroutine and does not return a value to the application. In most cases,
the application does not need to check the return from this call, since by default SWIM
traps all return codes except 0 and the NOTFOUND symbolic constant. However, in
special cases, where the SqlErrException statement is used to give the application
more control over error handling, the application will need to obtain the return code
and this function is used for that purpose.
The SqlErr function returns one of the following integer global constants declared in
Applic.DH:
Return Value
Description
DUPLICATE
See Also
SqlErrException Statement
Example
This example illustrates how to insert a uniquely numbered Batch record into the
database. The example assumes that a database transaction is already active when the
illustrated procedure is called. SqlErrException and SqlErr are used to detect
duplicate batch number error without causing Swim to abort the transaction. The
sample procedure receives two parameters:
394
As Integer
'Fetch the necessary fields for auto batch numbering from the Setup
'record specified by AutoNbr_SqlStr
AutoNbrFetch = SqlFetch1(CSR_AutoNbr, AutoNbr_SqlStr, AutoNbr,
LenB(AutoNbr))
Do
'Increment
AutoNbr.LastNbrUsed
Reference
Loop While (SqlErr() = DUPLICATE)
End Sub
395
396
SqlErrException Statement
Description
Toggle automatic error handling logic for one or more database error codes.
Syntax
Call SqlErrException (ToggleFlag, ErrorToExcept)
Remarks
By default, all error codes except 0 and NOTFOUND are trapped within SWIM and
are not returned to the application. To alter this behavior an application can use the
SqlErrException function to tell SWIM not to trap certain errors and instead return
them to the application. This statement is used in conjunction with the SqlErr
function.
Note that the application is responsible for toggling the exception back off once it is no
longer needed.
The SqlErrException statement uses the following arguments:
Argument
Type
Description
ToggleFlag
Integer
ErrorToExcept
Integer
See Also
SqlErr Function
Example
This example illustrates how to insert a uniquely numbered Batch record into the
database. The example assumes that a database transaction is already active when the
illustrated procedure is called. SqlErrException and SqlErr are used to detect
duplicate batch number error without causing Swim to abort the transaction. The
sample procedure receives two parameters:
Reference
397
As Integer
'Fetch the necessary fields for auto batch numbering from the Setup
' record specified by AutoNbr_SqlStr
AutoNbrFetch = SqlFetch1(CSR_AutoNbr, AutoNbr_SqlStr, AutoNbr,
LenB(AutoNbr))
Do
'Increment
AutoNbr.LastNbrUsed
398
End Sub
SqlExec Statement
Description
Execute an inline SQL statement.
Syntax
Call SqlExec(Cursor)
Remarks
Execute a dynamic SQL statement on a cursor previously initialized with calls to the
Sql and SqlSubst statements (in that order).
The SqlExec statement uses the following arguments:
Argument
Type
Description
Cursor
Integer
See Also
Sql Statement, SqlSubst Statement
Reference
399
SqlFetch Functions
Description
Used to initialize a new database view and immediately retrieve a composite record.
Syntax
RetVal = SqlFetch1(Cursor, SqlStr, bTable1, bTable1Length)
RetVal = SqlFetch4(Cursor, SqlStr, bTable1, bTable1Length, bTable2,
bTable2Length, bTable3, bTable3Length, bTable4, bTable4Length)
RetVal = SqlFetch8(Cursor, SqlStr, bTable1, bTable1Length, bTable2,
bTable2Length, bTable3, bTable3Length, bTable4, bTable4Length, bTable5,
bTable5Length, bTable6, bTable6Length, bTable7, bTable7Length, bTable8,
bTable8Length)
Remarks
In order to fetch information from the database a database view must first be initialized
specifying what tables, fields and restriction criteria are to be utilized. Secondly an
actual request for data from an existing view must be sent to the server. Each of the
SqlFetch1, SqlFetch4 and SqlFetch8 functions effectively perform both of these
operations in a single call which would otherwise require a combination of two calls
(e.g., Sql and SqlFetch1). In looping situations where a program needs to sequentially
read through multiple records in a view, these functions are convenient for initializing
the view and immediately fetching the first record. However they should not be used to
fetch subsequent records since the view is being re-established each time SqlFetch1,
SqlFetch4 or SqlFetch8 is called and therefore they will always only fetch the first
record in the view. In these cases, SFetch1, SFetch4 or SFetch8 can be used to fetch
subsequent records.
SqlFetch1 is designed for SQL statements returning data from a single table. For more
advanced SQL statements having one or more table joins either SqlFetch4 or
SqlFetch8 can be used.
The SqlFetch1 function uses the following arguments (SqlFetch4 and SqlFetch8
respectively have four and eight table structures and corresponding lengths. PNULL
should be passed for unused table structure parameters as well as a corresponding
length of zero such as PNULL, 0)
Argument
Type
Description
RetVal
Integer
Cursor
Integer
400
Argument
Type
Description
SqlStr
String
bTable1
User-defined
datatype
bTable1Length
Integer
DISTINCT keyword
GROUP BY clause
HAVING clause
Subqueries
See Also
Sql Statement, SqlFetch Functions, SParm Function, IParm Function, FParm
Function, DParm Function, SGroupFetch Functions
Reference
401
Example
The following code reads through all records in the Account table. It is assumed that
the Account_All stored procedure was created using the following text Select * from
Account where Acct LIKE @parm1 Order By Acct. In following example, all records
in the Account table will meet the restriction clause since a wildcard value (e.g.,
SQLWILDSTRING) is used for the one and only parameter to the stored procedure. In
this case a wildcard value can properly be passed for the value of @parm1 since this
parameter is associated with the LIKE keyword. Furthermore, since the Account_All
stored procedure only selects data from a single table (e.g., the Account table)
SqlFetch1 would be adequate. However in this example, SqlFetch4 is actually used to
illustrate how to pass PNULL,0 for unused table structure arguments.
Dim
CSR_Account
As Integer
Dim
SqlStr
As String
Dim
AcctFetch
As Integer
'Allocate cursor
Call SqlCursor( CSR_Account, NOLEVEL)
'Initialize cursor with a SQL stored procedure and immediately
'fetch first record
SqlStr = "Account_All" + SParm(SQLWILDSTRING)
AcctFetch = SqlFetch4(CSR_Account, SqlStr, bAccount, LenB(bAccount),
PNULL, 0, PNULL, 0, PNULL, 0)
'Read through all subsequent Account records
While (AcctFetch = 0)
AcctFetch = SFetch4(CSR_Account, bAccount, LenB(bAccount),
PNULL, 0, PNULL, 0, PNULL, 0)
Wend
402
SqlFree Statement
Description
Free a database cursor no longer needed by the application.
Syntax
Call SqlFree(Cursor)
Remarks
The SqlFree statement is used to deallocate cursors previously allocated with the
SqlCursor statement. The usage is this statement is entirely optional. It is normally
used when a cursor is no longer needed by an application whose total number of
cursors is very close to the maximum limit. All cursors are automatically released by
the system when the application terminates execution (e.g., when ScreenExit is
called).
The SqlFree statement uses the following arguments:
Argument
Type
Description
Cursor
Integer
See Also
SqlCursor Statement
Reference
403
SqlNoWait Statement
Description
Implement asynchronous query processing on Microsoft SQL Server.
Syntax
Call SQLNoWait (Cursor, SQLStr)
Remarks
By design, when Microsoft SQL Server processes a stored procedure, control is not
passed back to the calling application until the stored procedure has completed. For
lengthy stored procedures, the processing status timer is not updated, nor can the user
cancel the process by clicking Cancel. The SQLNoWait statement allows processing
of a large SQL statement or stored procedure on the server to start, and allows the
Process Status Window timer to be updated during the execution of the SQL statement.
When the application issues a SqlNoWait() call, control is not returned to the
application until the SQL statement has been executed.
If the user clicks Cancel during processing, the process is cancelled. When the user
clicks OK for the Process has been cancelled message in the Process Status Window,
the application and execution of the stored procedure or SQL statement is terminated.
This statement should only be used within a VB Tools process that has already issued a
Status( StartProcess) call. If no process has been started, BulletProof error 10247 is
generated by the Solomon kernel.
Any stored procedure that is called using SQLNoWait must have SET NOCOUNT
ON as its first command.
The SQLNoWait statement uses the following arguments:
Argument
Type
Description
Cursor
Integer
SQLStr
String
404
Example
Private Sub AsyncAPITest_Click()
Dim SQLStmt As String
Dim serr As Integer
' Call the AsyncTest stored procedure
SQLStmt = "AsyncTest"
' Start the process
Call Status(StartProcess, False, "", 0)
Call Status(0, False, "Processing Asynchronously", DISP_ONLY)
Call sqlNoWait(c2, SQLStmt)
serr = SqlErr()
' End The process
Call Status(EndProcess, False, "", 0)
End Sub
Reference
405
SqlRowCntrs Statement
Description
SqlRowCntrs informs the Solomon kernel to use update counters from the current
memory array row, and to use these update counters to perform database contention
checking.
Syntax
Call SqlRowCntrs(Handle, Cursor)
Remarks
SqlRowCntrs is used in the Update_Update event whenever the application program
wishes to bypass default database update behavior that is performed by the Solomon
kernel. It is used when the application program is performing updates from a SAFGrid
application on a line-by-line basis.
The SqlRowCntrs statement uses the following arguments:
Argument
Type
Description
MemHandle
Integer
Cursor
Integer
See Also
MFirst, MNext, DetailLoad, SQLFetch
Example
Sub Update1_Update(level%, insertflg%, levelsdone%, levelsleft%, retval%)
Dim MemRecFound%
Dim MaintFlg%
Dim DocFound%
'Begin the transaction
Call Tranbeg(True)
'Move to first row in the grid
MemRecFound = mfirst(MemHandle, MaintFlg)
While MemRecFound = 0
Select Case MaintFlg
406
Reference
407
SqlSubst Statement
Description
Specify a data value for a substitution parameter in an inline SQL statement previously
executed via the Sql function.
Syntax
Call SqlSubst(Cursor, ParmName, ParmValue)
Remarks
SqlSubst allows you to specify values for one or more substitution variables in an
inline SQL statement that is executed via the Sql statement. It is not to be used for a
stored procedure.
This statement must be called after the Sql statement and before the SqlExec
statement. It can be called any number of times before SqlExec is called, depending on
how may parameter values there are to substitute into the SQL statement.
The SqlSubst statement uses the following arguments:
Argument
Type
Description
Cursor
Integer
ParmName
String
ParmValue
String
See Also
Sql Statement, SqlExec Statement
408
Example
Dim CSR_AcctHist
As Integer
Dim SqlStr
As String
Dim AcctHist_Fetch
As Integer
Reference
409
Status Statement
Description
Report process status information to either the Process Status Window or the Event
Log or both.
Syntax
Call Status(OpCode, FatalError, InfoString, Destination)
Remarks
The Status statement is foundational to all processes developed with Tools for Visual
Basic. This statement is used to formally start a process, report progress and/or error
information during the process as well as formally end the process. Once a process has
completed, the user can review information relating to events which occurred during
the process in the Event Log which was generated by the application using the Status
statement.
Whenever the Status statement is used to report data values along with a
corresponding caption, it is recommended that the caption of a Label control be used
for the reported caption and that the data value be formatted with the SParm statement
if it is a string value. For example, if a particular Batch Number is to be reported then a
Label control should be created having a Caption property of Batch Number:. The
actual name of the Label control itself is not as important but perhaps this one could be
named lp_Batch where the lp portion of the name could signify that the Label is used
during the process. At any rate a particular Batch Number can subsequently be reported
with code similar to: lp_Batch.Caption + SParm(bBatch.BatNbr). The exact syntax
obviously will vary depending on whether a message is being utilized that can handle
replacement parameters. In that case the code would assume the form of:
lp_Batch.Caption + NL + SParm(bBatch.BatNbr). The advantage of utilizing Label
controls for string literals, such as caption values, is that it facilitates customization of
the actual reported text using the Customization Manager. Thus, for example, this
methodology makes it extremely easy for a particular process to be customized for a
particular language without the need to modify string literals in the underlying source
code.
410
Type
Description
OpCode
Integer
FatalError
Integer
Reference
Argument
Type
Description
InfoString
String
Information to be reported.
411
Integer
See Also
SetRestart Statement, TranBeg Statement, TranEnd Statement
Example
The Payroll Check Update process uses the following code to begin the process, report
errors during the process and lastly to end the process.
Two error messages can potentially be reported during the process depending on
various logical problems detected in data. Message #832 is assumed to have the
following associated text in the Solomon message file: Batch status is invalid for
processing. Lastly, message #6003 is assumed to have the following associated text:
Warning - %s %s is not found. Notice that the example code illustrates how to pass
data values to the two replaceable parameters in this particular message.
Dim SqlStr
As String
Dim Batch_Fetch
Dim Hold_Batch
'
to voided or deleted).
'
'
'
checks.
412
As Integer
'
'
'
Dim ParmStr
Any_Checks_KEPT
As String
'
Used for
Batches
' "K"
Reference
'If any checks at all were either KEPT or VOIDED then we
'will update the batch to be a "real" batch as opposed to
'VOIDING the batch.
If ((Any_Checks_KEPT = True) Or (Any_Checks_VOIDED =
True)) Then
bBatch.Descr = ""
bBatch.PerPost = bPerPost.Str
If (Any_Checks_KEPT = True) Then
bBatch.Status = "B"
Else
'All checks were voided - so batch will NOT be
'released to the General Ledger.
bBatch.Rlsed = LTRUE
bBatch.Status = "C"
End If
bBatch.User1 = ""
bBatch.User2 = ""
Else
'Re-initialize batch as a voided batch
Hold_Batch = bBatch
bBatch = nBatch
bBatch.BatNbr = Hold_Batch.BatNbr
bBatch.Module = Hold_Batch.Module
bBatch.PerPost = bPerPost.Str
bBatch.Rlsed = LTRUE
bBatch.Status = "V"
End If
Call SUpdate1(CSR_Batch, "Batch", bBatch, LenB(bBatch))
Else
'Batch status is invalid for processing.
Call Status(832, True, "", LOG_AND_DISP)
End If
'bBatch.Status
Else
'Warning - %s %s is not found.
Call Status(6003, True, lp_Batch.Caption + NL +
SParm(bBatch.BatNbr), LOG_AND_DISP)
End If
'Batch_Fetch
413
414
KEPT
Reference
415
StrToDate Statement
Description
Convert a date value from a string in MMDDYYYY format into a SQL date format.
Syntax
Call StrToDate(DateStringToConvert, SQLDate)
The StrToDate statement uses the following arguments:
Argument
Type
Description
DateStringToConvert
String
SQLDate
See Also
DateToIntlStr Function, DateToStr Function, DateToStrSep Function,
IntlStrToDate Statement
StrToTime Statement
Description
Convert a time value from a string in HHMMSShh format into a SQL time format.
Syntax
Call StrToTime(TimeStringToConvert, SQLTime)
The StrToTime statement uses the following arguments:
Argument
Type
Description
TimeStringToConvert
String
SQLTime
See Also
TimeToStr Function
416
SUpdate Statements
Description
Update one record of each specified table within an existing database view.
Syntax
Call SUpdate1(Cursor, TablesUpdating, bTable1, bTable1Length)
Call SUpdate4(Cursor, TablesUpdating, bTable1, bTable1Length, bTable2,
bTable2Length, bTable3, bTable3Length, bTable4, bTable4Length)
Call SUpdate8(Cursor, TablesUpdating, bTable1, bTable1Length, bTable2,
bTable2Length, bTable3, bTable3Length, bTable4, bTable4Length, bTable5,
bTable5Length, bTable6, bTable6Length, bTable7, bTable7Length, bTable8,
bTable8Length)
Remarks
Existing records can be programmatically updated directly via the use of the
SUpdate1, SUpdate4 and SUpdate8 statements. However, before a record can be
updated it must first be fetched using one of the SFetch1, SFetch4 and SFetch8 or
SqlFetch1, SqlFetch4 and SqlFetch8 functions. The fetch operation which precedes
the update must be made using the same database view / cursor on which the update
will occur. For example, if the fetch occurs on Cursor A then the update must also
occur on Cursor A as opposed to some unrelated Cursor XYZ. Nevertheless, once the
database view has been established these functions will update the current record in the
view for each table referenced in the TablesUpdating argument using data from
corresponding table structure arguments.
SUpdate1 is designed for SQL statements referencing a single table. In this case the
TablesUpdating is always the name of the single table actually referenced. For more
advanced SQL statements having one or more table joins either SUpdate4 or
SUpdate8 can be used. The referencing of more than one table does not automatically
force the current record of every table within the view to be updated anytime
SUpdate4 or SUpdate8 is used on the corresponding cursor. The current record of a
particular table in the view will only be updated if its corresponding table name is
explicitly specified in the TablesUpdating argument so long as each table name so
specified is also referenced in the SQL statement which was used to initialize the
current view. Thus, for example, if TableA and TableB are the only two tables
referenced in the SQL statement used to initialize the current view then a value of
TableXYZ would be invalid for the TablesUpdating argument.
Reference
417
The SUpdate1 function uses the following arguments (SUpdate4 and SUpdate8
respectively have four and eight table structures and corresponding lengths. PNULL
should be passed for unused table structure parameters as well as a corresponding
length of zero such as PNULL, 0)
Argument
Type
Description
Cursor
Integer
TablesUpdating
String
bTable1
User-defined datatype
bTable1Length
Integer
See Also
SFetch Functions, SqlFetch Functions, SqlCursor Statement
Example
This simple example will update all GLTran records in General Ledger Batch 000001
as being released. Within Solomon, the release of GLTran records actually entails
additional application logic which is not directly relevant to the illustration of the
SUpdate4 statement and therefore it has been removed from this example.
418
= @parm1
= @parm2
Since the above SQL statement only retrieves data from a single table (e.g., the
GLTran table) SUpdate1 would be adequate. However in this example, SUpdate4 is
actually used to illustrate how to pass PNULL, 0 for unused table structure arguments.
Dim CSR_GLTran
As Integer
Dim SqlStr
As String
Dim GLTranFetch
As Integer
'used to speed up performance since ALL GLTran records read within the
'database transaction will also be updated.
Call SqlCursor( CSR_GLTran, NOLEVEL + SqlList)
Reference
419
While (GLTranFetch = 0)
'Release current transaction
bGLTran.Posted
= "U"
bGLTran.Rlsed
= LTRUE
'Update the record last fetched on CSR_GLTran (e.g. the current GLTran
'record) with the modified contents of bGLTran
Call SUpdate4(CSR_GLTran, "GLTran", bGLTran, LenB(bGLTran),
PNULL, 0, PNULL, 0, PNULL, 0)
'Load next transaction record
GLTranFetch = SFetch4(CSR_GLTran, bGLTran, LenB(bGLTran),
PNULL, 0, PNULL, 0, PNULL, 0)
Wend
420
SwimGetProfile Function
Description
Return the value of a specific entry within the designated INI file.
Syntax
INIEntryValue = SwimGetProfile( INISection, INIEntry, DefaultValue, MaxEntrySize,
INIFileName)
Remarks
SwimGetProfile will read the given INI file and return the current contents of the
designated INIEntry. The system will search for the INIFileName in the workstations
Windows directory. If the file does not exist or the designated entry is not found, the
system will read the INIFileName in the Solomon program directory. If the desired
INIEntry cannot be located after searching both of these locations then the
DefaultValue is returned.
The SwimGetProfile function uses the following arguments:
Argument
Type
Description
INIEntryValue
String
INISection
String
INIEntry
String
DefaultValue
String
MaxEntrySize
Integer
INIFileName
String
See Also
SwimWriteProfile Function
Reference
421
SwimWriteProfile Function
Description
Write a new value for a specific entry within the designated INI file.
Syntax
RetVal = SwimWriteProfile(INISection, INIEntry, INIEntryValue, INIFileName)
Remarks
The SwimGetProfile function uses the following arguments:
Argument
Type
Description
RetVal
Integer
INISection
String
INIEntry
String
INIEntryValue
String
INIFileName
String
See Also
SwimGetProfile Function
422
TestLevelChg Function
Description
Return the current update status flag for a specific level.
Syntax
Status = TestLevelChg(LevelNbr)
Remarks
Each update level, as defined by the Levels property of the SAFUpdate control, has a
corresponding level status flag that is automatically maintained by the system. The
purpose of the level status flag is to facilitate the optimization of database updates
performed in response to Parent toolbar buttons. In general, these flags allow the
system to only perform database updates for update levels which have in fact changed.
If no information has changed then no information needs to be saved.
As previously mentioned, these update flags are automatically maintained by the
system. When an existing record is loaded the flag is set to NOTCHANGED. If any
non-keyfield is subsequently modified then the level status flag for the corresponding
level is set to UPDATED. When a new record is being entered, the level status flag is
set to INSERTED.
The TestLevelChg function allows the application to access the current value of this
flag for a specific level. The current level status flag can be overridden by the
application using the SetLevelChg statement.
The TestLevelChg function uses the following arguments:
Argument
Type
Description
Status
Integer
LevelNbr
Integer
See Also
SetLevelChg Statement
Reference
423
Example
The Payroll Earnings Type Maintenance screen contains a button to automatically
populate the grid with all Deductions. This amounts to inserting records into the grid
(e.g., into its underlying memory array) under program control. Since the data is not
entered via the user interface by the user, the system needs to be notified that
information at the grid level (e.g., LEVEL1 in this case) has been programmatically
updated and therefore needs to be saved. However, such notification only needs to
occur if the system is not already aware that data has changed.
'If any records were inserted into the memory array then we need to make
'sure that the level status for the detail level is something other than
'NOTCHANGED so the system will know that something needs to be saved.
If (AnyRecsInserted = True) Then
If (TestLevelChg(LEVEL1) = NOTCHANGED) Then
Call SetLevelChg(LEVEL1, UPDATED)
End If
End If
424
TimeToStr Function
Description
Convert a time value from SQL time format into a string in HHMMSShh format.
Syntax
TimeString = TimeToStr(TimeToConvert)
Remarks
The TimeToStr function uses the following arguments:
Argument
Type
Description
TimeString
String
TimeToConvert
See Also
StrToTime Statement
TranAbort Statement
Description
Abort the current database transaction.
Syntax
Call TranAbort
Remarks
The TranAbort statement allows the application to abort a database transaction which
was initiated using the TranBeg statement.
Calling TranAbort directly is not, however, the recommended method to abort
transactions. If the transaction to be aborted is an update operation for an application
screen then the recommended method is for the application to set RetVal in the Update
event of the SAFUpdate control to either an error message number or the ErrNoMess
symbolic constant defined in Applic.DH. On the other hand, if the abort is to occur
during a process then a fatal error message should be written to the Event Log using
the Status statement. This will also have the effect of aborting the current database
transaction.
See Also
Status Statement, TranBeg Statement, TranEnd Statement, Update Event
Reference
425
TranBeg Statement
Description
Begin a database transaction.
Syntax
Call TranBeg(IsAbortable)
Remarks
All updates to the database must occur within a database transaction.
All updates to the database will not actually be committed to the database until the
transaction is ended via the TranEnd statement.
If any errors occur during the database transaction then the system will automatically
abort (e.g., roll back) all updates occurring during the transaction as opposed to
committing them to the database. If the transaction is an update operation for an
application screen then it will be aborted when the application to sets RetVal in the
Update event of the SAFUpdate control to either an error message number or the
ErrNoMess symbolic constant defined in Applic.DH. On the other hand, if the
transaction occurs during a process then it will be aborted when a fatal error message is
reported using the Status statement.
The TranBeg statement uses the following argument:
Argument
Type
Description
IsAbortable
Integer
See Also
Status Statement, TranEnd Statement, TranStatus Function, Update Event
426
TranEnd Statement
Description
End the current database transaction and commit all updates to the database.
Syntax
Call TranEnd
Remarks
If any errors occurred during the database transaction then the system will
automatically abort (e.g., roll back) all updates which occurred during the transaction
as opposed to committing them to the database. If the transaction is an update
operation for an application screen then it will be aborted when the application to sets
RetVal in the Update event of the SAFUpdate control to either an error message
number or the ErrNoMess symbolic constant defined in Applic.DH. On the other hand,
if the transaction occurs during a process then it will be aborted when a fatal error
message is reported using the Status statement.
See Also
Status Statement, TranBeg Statement, TranStatus Function, Update Event
TranStatus Function
Description
Returns the status of the current or last database transaction.
Syntax
IntegerErrVal = TranStatus()
Remarks
If a database transaction is currently not open then the status of the last performed
database transaction is returned.
A return value of zero indicates that the transaction was successful.
A non-zero return value indicates a fatal error occurred during the transaction and
therefore it will be, or was, aborted. In this case, the actual return value itself is the
number of the error message describing the nature of the problem.
See Also
Status Statement, TranBeg Statement, TranEnd Statement, Update Event
Limit
Number of Levels
10
Number of SAFGrids
10
16
Unlimited
36
Unlimited
1000
427