Function SRP_EditTable_Manager(Method, CtrlEntId, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10) /*********************************************************************************************************************** This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written permission from SRP Computer Solutions, Inc. Name : SRP_EditTable_Manager Description : Provides common setup and event features for the SRP OLE EditTable. Notes : This is desiged to eliviate the need to duplicate large amounts of code to manage the SRP OLE EditTable. Review the list of options in the top-level case statement of this program to see what is available. Some methods will call other methods. For instance, the BeforeUpdate method will call the Validate method. Parameters : Method [in] -- A specific setup or event action to execute. CtrlEntId [in] -- The full control entity ID for the SRP OLE EditTable. Param2 [in] -- Generic parameter. Param3 [in] -- Generic parameter. Param4 [in] -- Generic parameter. Param5 [in] -- Generic parameter. Param6 [in] -- Generic parameter. Param7 [in] -- Generic parameter. Param8 [in] -- Generic parameter. Param9 [in] -- Generic parameter. Param10 [in] -- Generic parameter. EventFlow [out] -- Flag to indicate how the calling routine should continue. This will return a 1 if everything is successful. History : (Date, Initials, Notes) 01/22/08 dmb Original programmer. Start with the Validate method. 01/24/08 dmb Add Clear and Read methods. Updated the WritePre method. 01/25/08 dmb Add GridLine color defaults for Setup1. 01/26/08 dmb Add Fill flag for Clear method. 01/26/08 dmb Add PopulateData method. 01/26/08 dmb Move LostFocus transfer data logic into its own gosub. 02/14/08 dmb Add support for custom clear fills (used by the Clear method). Add support for @ROWSASCOLUMNS and @CELLSASFIELDS UDPs (used by Set_Record). 02/14/08 dmb Update Style1 to default all header row and data rows to 19 pixels and not resizeable. 02/16/08 dmb Add support for new UpdateCellEdit parameter in Transfer_EditTable_Data function. Only set it to Yes$ during the WritePre method. ***********************************************************************************************************************/ $insert LOGICAL GoSub Check_Variable_Assignments Declare function SRP_Edittable_Manager, Get_Property, Send_Message Declare subroutine Transfer_Edittable_Data, SRP_Edittable_Manager, Set_Record, Send_Message, Set_Property Begin Case // EditTable Events Case Method EQ "BeforeUpdate" ; GoSub BeforeUpdate Case Method EQ "AfterUpdate" ; GoSub AfterUpdate Case Method EQ "PosChanged" ; GoSub PosChanged Case Method EQ "AfterDeleteRecords" ; GoSub AfterDeleteRecords Case Method EQ "LostFocus" ; GoSub LostFocus // Window Events Case Method EQ "WritePre" ; GoSub WritePre Case Method EQ "Read" ; GoSub Read Case Method EQ "Clear" ; GoSub Clear // Event actions Case Method EQ "Validate" ; GoSub Validate Case Method EQ "Convert" ; GoSub Convert // Data population Case Method EQ "PopulateData" ; GoSub PopulateData // Setup options Case Method EQ "Setup1" ; GoSub Setup1 End Case If Assigned(EventFlow) else EventFlow = 1 ; // If not method set this then assume all is well Return EventFlow Validate: ////////////////////////////////////////////////////////////////////////////////////// // // The Validate method requires the following parameters to be populated: // // Param1 = SelPos // Param2 = Data // Param3 = Validation // // Optionally, these parameters can also be use to override default settings: // // Param4 = ValidationMessage // Param5 = ValidationTitle // Param6 = ValidationDisplayLength // // If ValidationMessage is populated then the ShowBalloonTooltip will be used. // Otherwise, it is assumed tha the validation method will display its own // message, which is the case for many UDCs. // ////////////////////////////////////////////////////////////////////////////////////// Transfer Param1 to SelPos Transfer Param2 to Data Transfer Param3 to Validation Transfer Param4 to ValidationMessage If Len(Param5) then Transfer Param5 to ValidationTitle else ValidationTitle = "Validation Error" If Len(Param6) then Transfer Param6 to ValidationDisplayLength else ValidationDisplayLength = 2000 Status() = 0 iData = IConv(Data, Validation) If Status() NE 0 then // Validation failed. If Len(ValidationMessage) then // Use the ShowBalloonTooltip to alert the user of the validation error. Convert ";" to @FM in SelPos Swap "@DATA" with Data in ValidationMessage Config = "" Config<1> = ValidationMessage ; // Message to display. Config<2> = ValidationTitle ; // Title of the message. Config<3> = 3 ; // Use the Error icon. Config<4> = ValidationDisplayLength ; // Display for 2 seconds unless user clicks to close first. Send_Message(CtrlEntId, "OLE.ShowBalloonTooltip", SelPos, Config) end Set_Property(CtrlEntId, "OLE.Cancel", 2) ; // This forces the focus to return to the current cell and highlight the cell text. EventFlow = 0 ; // Indicate that this event chain needs to abort. end return Convert: ////////////////////////////////////////////////////////////////////////////////////// // // The Convert method requires the following parameters to be populated: // // Param1 = SelPos // Param2 = Data // Param3 = Conversion // ////////////////////////////////////////////////////////////////////////////////////// Transfer Param1 to SelPos Transfer Param2 to Data Transfer Param3 to Conversion NewData = Oconv(Iconv(Data, Conversion), Conversion) ; // Internally convert then externally convert the data to make sure it is formatted correctly. Set_Property(CtrlEntId, "OLE.CellText[":SelPos:"]", NewData) return BeforeUpdate: // The BeforeUpdate event can be used for validation checking. Transfer Param1 to SelPos Transfer Param2 to Data Transfer Param3 to Validation CellConv = Get_Property(CtrlEntId, "OLE.CellConv[":SelPos:"]") ValidationMessage = CellConv<3> // If the Validation parameter has something, do a validation check. If Len(Validation) then EventFlow = SRP_EditTable_Manager("Validate", CtrlEntId, SelPos, Data, Validation, ValidationMessage) end return AfterUpdate: // The AfterUpdate event can be used for conversion. Transfer Param1 to SelPos Transfer Param2 to Data Transfer Param3 to Conversion // If the Conversion parameter has something, perform the conversion. If Len(Conversion) then SRP_EditTable_Manager("Convert", CtrlEntId, SelPos, Data, Conversion) return PosChanged: // The PosChanged event can be used for defaults. Transfer Param1 to SelPos Transfer Param2 to PrevSelPos Transfer Param3 to Cause Transfer Param4 to Default ; // Note: this parameter is not a part of the PosChanged event // but the calling routine can pass this in to allow default handling. // Get the data in the current cell. If null and a default value has been passed in then update the cell text. Data = Get_Property(CtrlEntId, "OLE.CellText[":SelPos:"]") If Data EQ "" AND Len(Default) then Set_Property(CtrlEntId, "OLE.CellText[":SelPos:"]", Default) Send_Message(CtrlEntId, "OLE.EditCell", "") end // Since the PosChanged event can add default data make sure these changes are transferred to the OI EditTable. UpdateCellEdit = No$ GoSub Update_Databound_EditTable return AfterDeleteRecords: // Since deleting a record from the EditTable changes data make sure these changes are transferred to the OI // EditTable. UpdateCellEdit = No$ GoSub Update_Databound_EditTable return LostFocus: UpdateCellEdit = No$ GoSub Update_Databound_EditTable return Read: Record = Param1 Set_Record(Record, "", Yes$) return Clear: // Find all the OLE EditTables and Clear them. Transfer Param1 to DefaultClearFill If DefaultClearFill EQ "" then DefaultClearFill = 1 CtrlMap = Get_Property(@Window, "CTRLMAP") Convert @FM to @RM in CtrlMap ProgIDs = Get_Property(CtrlMap, "OLE.ProgID") BytePos = 1 ; // Byte position within the string. Used by the Remove statement Flag = "" ; // Flag used by the Remove statement RPos = 0 ; // Record position within the @RM delimited string Loop Remove ProgID from ProgIDs at BytePos setting Flag RPos += 1 If ProgID _EQC "SRP.EditTable.1" then // This is an OLE EditTable so send the Clear method. Ctrl = Field(CtrlMap, @RM, RPos) ClearFill = Get_Property(Ctrl, "@CLEARFILL") If ClearFill EQ "" then ClearFill = DefaultClearFill Send_Message(Ctrl, "OLE.Clear", ClearFill) end While Flag Repeat return WritePre: CtrlEntId = Get_Property(@Window, "FOCUS") ProgID = Get_Property(CtrlEntId, "OLE.ProgID") If ProgID _EQC "SRP.EditTable.1" then // Control with focus is an SRP OLE EditTable. Before the system event handler executes, update the current cell // text and then transfer the data from the OLE EditTable to the OI EditTable. CellContents = Send_Message(CtrlEntId, "OLE.UpdateCellEdit") If CellContents<2> EQ "" then // The attempt to update the cell failed. Probably due to a validation error. Abort the event. EventFlow = 0 end else // Cell update was successful. Transfer data to OI EditTable. UpdateCellEdit = Yes$ GoSub Update_Databound_EditTable end end return PopulateData: // It is assumed that @ID, @RECORD, and @DICT is already populated. This method uses // the Calculate function which requires these system variables. Transfer Param1 to DataArray ; // Dynamic array of field names. Used by the Calculate function to compute the value. DictFields = Param2 ; // The %FIELDS% record from the dictionary table. Used to get the output conversion format. Transfer Param3 to ArrayFlag ; // Flag that indicates if the DataArray is in Array or List format. Default is Array. If ArrayFlag EQ "" then ArrayFlag = Yes$ NumRows = FieldCount(DataArray, @FM) For RowCnt = 1 to NumRows NumCols = FieldCount(DataArray, @VM) For ColCnt = 1 to NumCols FieldName = DataArray Locate FieldName in DictFields<3> using @VM setting vPos then FieldData = Calculate(FieldName) Format = DictFields<12, vPos> If Len(Format) then FieldData = Oconv(FieldData, Format) DataArray = FieldData end Next ColCnt Next RowCnt If ArrayFlag then Prop = "OLE.Array" else Prop = "OLE.List" Set_Property(CtrlEntId, Prop, DataArray) return Setup1: Transfer Param1 to ArrayDimension Transfer Param2 to TitleList Transfer Param3 to ColumnWidths Transfer Param4 to ColumnAlignments Transfer Param5 to VirtualPos Transfer Param6 to RowsAsColumns Transfer Param7 to CellsAsFields Transfer Param8 to ClearFill Transfer Param9 to RowsToRecord // Set up general properties that affect the entire EditTable. Set_Property(CtrlEntId, "OLE.BorderType", "XP Flat") ; // XP border when possible. Set_Property(CtrlEntId, "OLE.WorkspaceBkColor", "Window") ; // Fill in the space with no cells with the current theme's Window color. If ArrayDimension then Set_Property(CtrlEntId, "OLE.Dimension", ArrayDimension) ; // Create the number of columns and rows for this EditTable. If RowsToRecord then Set_Property(CtrlEntId, "OLE.RowsToRecords", RowsToRecord) ; // Set up RowsToRecord if required. // Set up properties that affect navigation functional and visual behavior. Set_Property(CtrlEntId, "OLE.QuickTabOut", Yes$) ; // Force the focus to move to the next control if the user tries to navigate on an empty row (i.e. just like AREV). "Yes" is the default, but it is added here anyway to help explain what the EditTable can do. Set_Property(CtrlEntId, "OLE.CellEditMode[All; All]", "Edit") ; // Put the cell into edit mode upon entry. Notice that properties that accept coordinates can accept the keyword "All". Set_Property(CtrlEntId, "OLE.AutoColors" , "Row(Auto; Auto; Auto; 3DFace L=95; 1)") ; // Automatically alternate the color of every other row. This makes different rows easier to identify, especially since we have set 2 RowsToRecord. Set_Property(CtrlEntId, "OLE.SelectionStyle", @VM:"S L=80":@FM:@VM:"S L=95") ; // Automatically highlight the current row with one color and highlight the current row with another color. // Set up the Column and Row headers. If Len(TitleList) then If TitleList then Set_Property(CtrlEntId, "OLE.TitleList", TitleList) ; // Set up the text to be displayed in each column header. end else Set_Property(CtrlEntId, "OLE.HeaderRow[1]", @FM:No$) ; // Hide the header row if no TitleList was passed in. end Set_Property(CtrlEntId, 'OLE.HeaderFont[All;All]', 'Segoe UI' : @SVM : 9) Set_Property(CtrlEntId, 'OLE.CellFont[All;All]', 'Segoe UI' : @SVM : 9) Set_Property(CtrlEntId, "OLE.HeaderRow[All]", "19":@FM:"":@FM:No$) ; // Make all column header rows to be 19 pixels tall and unable to be resized. Set_Property(CtrlEntId, "OLE.DataRow[All]", "19":@FM:"":@FM:No$) ; // Make all data rows to be 19 pixels tall and unable to be resized. Set_Property(CtrlEntId, "OLE.HeaderColumn[1]", "20":@FM:"":@FM:No$) ; // Make the row header column to be 20 pixels wide and unable to be resized. Set_Property(CtrlEntId, "OLE.AutoNumbers", "I":@VM:1) ; // Make the row header column auto number with an integer starting with 1. // Set up column properties. If ColumnWidths then NumColumns = Count(ColumnWidths, @FM) + (ColumnWidths NE "") CharPos = 1 For ColPos = 1 to NumColumns Remove ColWidth from ColumnWidths at CharPos setting Flag Begin Case Case Num(ColWidth) ; Set_Property(CtrlEntId, "OLE.DataColumn[":ColPos:"]", ColWidth) ; // Set column to fixed width Case ColWidth EQ "A" ; Set_Property(CtrlEntId, "OLE.DataColumn[":ColPos:"]", @FM:@FM:@FM:Yes$) ; // Set column to autosized End Case Next ColPos end If ColumnAlignments then NumColumns = Count(ColumnAlignments, @FM) + (ColumnAlignments NE "") CharPos = 1 For ColPos = 1 to NumColumns Remove ColumnAlignment from ColumnAlignments at CharPos setting Flag If Len(ColumnAlignment) then Set_Property(CtrlEntId, "OLE.CellAlignment[":ColPos:"; All]", @FM:ColumnAlignment) ; // Set the column alignment Next ColPos end // Set up the @POS UDP for Set_Record If VirtualPos then Set_Property(CtrlEntId, "@POS", VirtualPos) If RowsAsColumns then Set_Property(CtrlEntId, "@ROWSASCOLUMNS", RowsAsColumns) If CellsAsFields then Set_Property(CtrlEntId, "@CELLSASFIELDS", CellsAsFields) If ClearFill then Set_Property(CtrlEntId, "@CLEARFILL", ClearFill) GoSub Qualify_Events return ////////////////////////////////////////////////////////////////// ///////////////// Internal methods /////////////////////////////// ////////////////////////////////////////////////////////////////// Check_Variable_Assignments: If Assigned(Method) else Method = "" If Assigned(CtrlEntId) else CtrlEntId = "" If Assigned(Param1) else Param1 = "" If Assigned(Param2) else Param2 = "" If Assigned(Param3) else Param3 = "" If Assigned(Param4) else Param4 = "" If Assigned(Param5) else Param5 = "" If Assigned(Param6) else Param6 = "" If Assigned(Param7) else Param7 = "" If Assigned(Param8) else Param8 = "" If Assigned(Param9) else Param9 = "" If Assigned(Param10) else Param10 = "" return ParseParam1: SelPos1 = Param1 FieldPos1 = Field(SelPos1, ";", 1) RecordPos1 = Field(SelPos1, ";", 2) return ParseParam2: SelPos2 = Param2 FieldPos2 = Field(SelPos2, ";", 1) RecordPos2 = Field(SelPos2, ";", 2) return Update_Databound_EditTable: // Transfer the Array property of the OLE EditTable to the DEFPROP property of the OI EditTable. Assumes that the // OLE EditTable begins with "OLE_EDT" and that the OI EditTable begins with "EDT" and it also assumes the rest of // the control names match. OIEditTable = CtrlEntId Swap "OLE_EDT" with "EDT" in OIEditTable Transfer_EditTable_Data(CtrlEntId, OIEditTable, No$, UpdateCellEdit) // Force a redisplay of any symbolic columns in the window. Set_Record("", "SYM") return Qualify_Events: // Enable OLE event processing for this control. Set the Synchronous event flag for better event control. Qualify = "" Qualify<1> = 1 ; // Enable OLE event Qualify<4> = 2 ; // Synchronous event processing Send_Message(CtrlEntId, "QUALIFY_EVENT", "ALL_OLES", Qualify) return