Extending Ready-Made Applications |
You can modify SAS/EIS objects by writing your own methods to replace the methods that are shipped with SAS/EIS software. You can use this technique to augment the functionality of the objects that are supplied by SAS/EIS, or to change the way the objects that you develop work. In general, the steps for overriding a method are:
Review the object's functionality and identify what you want to customize.
Determine which model or viewer methods you want to override.
Using the Methods tab of the Advanced window, override the appropriate method.
Implement any other windows or menus that are required for the customization.
In the Multidimensional Report, you can change the columns that are displayed in the report by opening the Report Layout window from the Edit pull-down menu. This window enables users to change the dimensions displayed down and across the report, along with the analysis columns. However, this example shows you how to change the analysis columns without opening the Report Layout window. By clicking on the label of a currently displayed analysis column, users can select from a list of other available analysis columns. The following steps show you how to design, code, and test this customization.
Step 1: Review the object's functionality and identify what you want to customize |
In the Multidimensional Report, an item called Report Layout is available from the pull-down menu and the pop-up menu. When you select Report Layout, the Column Selection window opens. You can then select new dimensions or analysis columns that you want to display in the report.
Instead of using this window to change the report layout, you can add the ability to single-click the label of an analysis column and enable your users to select from a list of currently available columns. When a user selects a column, it will replace the analysis column that was originally selected.
Step 2: Determine which model or viewer methods to override |
When an EIS application executes, the viewer for the application is instantiated within a frame. The multidimensional data model (SASHELP.MDDB.EMDDB_M.CLASS) is also instantiated and attached to the viewer. The data model organizes the data to be displayed and the viewer displays it. So, for the Multidimensional Report, the viewer SASHELP.EIS.TABLET_V.CLASS is instantiated and the data model is attached. When overriding methods, you can override either model methods or viewer methods.
In this case, you want to change what happens when the user clicks on the viewer. Looking at SAS/EIS Software Flow of Control, you can see that the _objectLabel method executes when the user clicks on the viewer. This is the method that you will override.
Step 3: Code the override |
When coding the override, consider whether the override adds to the method's normal functionality or whether it redefines the existing method. If the override adds to the existing functionality, then the override must use the SUPER CALL routine to execute the inherited definition of the method. Otherwise, a SUPER CALL is not required. The override can use any existing viewer methods and model methods, or any existing attributes, along with any other standard SCL function.
In this example, you will be adding to existing functionality, so your method must include a SUPER CALL to execute the inherited _objectLabel method. You will also be using several model methods to determine what the user clicked on, to determine which analysis columns are available, and to change the analysis column once a user makes a selection. The flow for the override is as follows:
Determine whether the user's action is a single click. If not, then return.
Find the active value -- for example, what the user clicked on.
If the user did not click on an analysis column label, then return.
Replace the original analysis column with the one that the user selected.
See the complete code in Example Code.
Step 4: Override the appropriate method |
For each report that will use this override, you need to apply the override by going to the Methods tab in the Advanced window. The Methods tab provides easy access to a set of methods that are commonly overridden for the model and viewer class. You can specify a per-instance method for any of the methods listed by entering the appropriate values in this tab. (A per-instance method enables you to add to or override a method for a specific object in an application.) The per-instance method is then applied to the class at run time. The steps for doing this are:
In the Build EIS window, select the report that will use the override. Then click .
Select the Viewer radio box for the Object, if it is not already selected. A list of viewer methods is displayed in the list box.
Select _objectLabel and then type the name of an SCL entry in the Source Entry field. Type EXCHANGE in the Source Label field.
Since you will be using a CALL SUPER routine within your code, select the Override radio box for When to Run.
Note: If you want to apply this method override to many reports, you will need to subclass the viewer to add the new method functionality.
Step 5: Implement any other windows or menus that are required for the customization |
This example does not require any other windows or menus. However, if you were adding items to the pull-down menus, you could also specify a new pull-down menu from within the Advanced window after you use PROC PMENU to create the menu.
Step 6: Test the override |
After you specify the override, click in the Advanced window to return to the report's build window. Then click . When the report appears, select one of the analysis column labels and verify that the list of available columns is displayed. Select one and verify that it replaces the analysis column that was originally selected.
Example Code |
Use the following code to override methods:
/* Copyright(c) 2004 by SAS Institute Inc., Cary, NC USA */ /*-------------------------------------------------------+ | Set SCL variable lengths and declare model as an object. +-------------------------------------------------------*/ length class_name $ 32 oldname $ 32 status $ 1 rc 8 currcol $ 256; dcl object modelid; /*-------------------------------------------------------+ | Initialize attributes to remove warnings. +-------------------------------------------------------*/ modelid = modelid; _self_ = _self_; _frame_ = _frame_; oldname = oldname; exchange: method; /*-------------------------------------------------------+ | Call super. +-------------------------------------------------------*/ call super(_self_,'_object_label_'); /* get the frames status */ /*-------------------------------------------------------+ | Get the frame status. If not single click, return. +-------------------------------------------------------*/ call send(_frame_,'_get_status_',status); if status ^= '' then return; /*-------------------------------------------------------+ | Get the current active value. +-------------------------------------------------------*/ cell_list = makelist(); hlist = makelist(); modelid._getActiveValue(cell_list,class_name,hlist); /*-------------------------------------------------------+ | Determine what the user clicked on. | If not an analysis column, then return. +-------------------------------------------------------*/ if class_name ^= '_ANLSYS_' then return; /*-------------------------------------------------------+ | Save the name of the column the user clicked on. +-------------------------------------------------------*/ currcol = getnitemc(cell_list,'_ANLSYS_'); /*-------------------------------------------------------+ | Get a list of all columns from the model. +-------------------------------------------------------*/ allvars = makelist(); modelid._getVarinfo(allvars); /*-------------------------------------------------------+ | Get a list of all displayed analysis columns. | DISPVARS is a list of the analysis column labels. +-------------------------------------------------------*/ dispvars = makelist(); modelid._getDisplayedClassValues('_ANLSYS_',dispvars); /*-------------------------------------------------------+ | Build the list of non-displayed analysis columns. +-------------------------------------------------------*/ poplist = makelist(); do x = 1 to listlen(allvars); sublist = getiteml(allvars,x); if nameditem(sublist,'ANALYSIS') | nameditem(sublist,'COMPUTED') then do; varlabel = getnitemc(sublist,'VARLABEL'); if not searchc(dispvars,varlabel) then do; varname = getnitemc(sublist,'VARNAME'); rc = insertc(poplist,varlabel,-1,varname); end; end; end; /*-------------------------------------------------------+ | Display the list and wait for the user's selection. +-------------------------------------------------------*/ pos = popmenu(poplist); /*-------------------------------------------------------+ | If a selection was made (pos > 0), process it. | The _changeAnalysis method requires a list in the | format: 'varname' = 'varlabel' | The list DISPVARS currently has only column labels. | To build the list for _changeAnalysis: | Call _getAnalysisVars to get a list of column names. | Call _getAnalysisLabels to get a list of column names | and labels. | Replace the current label/name with the selected one. +-------------------------------------------------------*/ if pos then do; templist = makelist(); modelid._getAnalysisVars(dispvars,templist); rc = clearlist(dispvars); modelid._getAnalysisLabels(templist,dispvars); curpos = searchc(dispvars,currcol); varlabel = getitemc(poplist,pos); varname = nameitem(poplist,pos); rc = setitemc(dispvars,varlabel,curpos); oldname = nameitem(dispvars,curpos,varname); modelid._changeAnalysis(dispvars); templist = dellist(templist); end; /*-------------------------------------------------------+ | Clean up lists and return. | +-------------------------------------------------------*/ rc = dellist(allvars,'Y'); rc = dellist(poplist); rc = dellist(dispvars,'Y'); endmethod;
Adding Methods to the Model |
In this example, you extended the functionality of the viewer. You can use this same technique to extend or change the functionality of the model. This example overrides an existing method; however, you can also add methods by overriding the viewer's _postInit method with something like the following code:
postInit: method; _self_._setInstanceMethod('_newViewerMethod','source-entry-name', 'label'); _self_.modelid._setInstanceMethod('newModelMethod','source','label'); call super(_self_,'_postInit'); endmethod;
The above example adds a new method called _newViewerMethod to the viewer and adds a new method called _newModelMethod to the model.
Copyright © 2007 by SAS Institute Inc., Cary, NC, USA. All rights reserved.