DECUS U. S. Chapter SIGs Newsletter, Volume 5, Number 1 September 1989 Wombat Examiner, Volume 11, Number 1 ---------------------------------------------------------------- DTR/DECREPORTER: User's Friend Jim Copenhaver, Simons-Eastern Consultants, Inc., Decatur, GA ---------------------------------------------------------------- The Computer Systems and Support department at Simons (Atlanta Region) was presented with a challenging problem. We had a rapidly growing user population comprised of managers, department heads, and staff personnel that had little exposure to a VAX and the flexibility and versatility available to them. This group, almost overnight, required access to data that had previously only been available to them via weekly reports. Each individual had specific needs for extracting data that varied drastically from user to user. Because of the large number of users, it was not possible for us to tailor the reports for each specific user. Since many of our weekly reports were produced with DATATRIEVE, it seemed like DATATRIEVE would be the logical solution for reporting problems. Unfortunately, several new users were confused by DATATRIEVE and cluttered up the CDD with aborted procedures. Our solution was to use DECREPORTER in conjunction with DATATRIEVE to provide the users with a platform for producing reports. We called this platform "Simons_Reporter". I took a "cookbook" approach that will allow anyone (with a familiarity with the CDD, DATATRIEVE, and DECREPORTER) to set up a similar platform. I reduced the process down to seven phases. Each phase, if followed, will step you through the creation of the platform. PHASE 1: For those unfamiliar with the CDD, the first phase is the most important and the most difficult to implement. It involves using the CDD utility DMU and how the CDD protections differ from those of VMS. If anyone needs to look up what, exactly the privileges shown here are, please refer to page A-48 in the VAX/CDD/Plus User's Guide (VAX/CDD/Plus V4.0). The following DMU commands will create either a CDD subdictionary or a CDD directory. Most applications will not need to create a separate subdictionary, and the *.dic file associated with it. Your specific needs may require this for security, space considerations, or some other reason, so it is listed here. DMU> CREATE CDD$TOP.SYSTEMS.SIMONS_REPORTER DMU> CREATE/SUBDICTIONARY=CDD$DSK:SIMONS_REPORTER.DIC SIMONS_REPORTER Here I have entered DMU and created the directory to house my platform. Notice that I specified the entire CDD path name for this dictionary. The New CDD is more selective and will not allow you to be as "careless" when you create a dictionary using DMU. Be sure that if you create a subdictionary that the *.dic file created has the VMS protections set to allow proper user access. Protection on the subdictionary and some of its objects might look like: _CDD$TOP.SYSTEMS.SIMONS_REPORTER 1. [*,*], Username: "DBADMIN" Grant - CDHPSX, Deny - none, Banish - none 2. [ENG_APPL] Grant - DEMPRSUWX, Deny - none, Banish - none 3. [*,*], Username: "JCOPENHAVER" Grant - DEMPRSUWX, Deny - none, Banish - none 4. [*,*] Grant - EPRS, Deny - none, Banish - none SIMONS_REPORTER.TIME_REPORTING_SYSTEM;2 Access Control List is empty SIMONS_REPORTER.TIME_REPORTING_SYSTEM_REC;1 Access Control List is empty Here, I have several commands to set the protections on the new directory. These protections allow specific users or groups of users limited access to the directory. The EPRS protection for the general users is most important. This allows users to access all of the existing reports or to create new reports. This will become more important later. For the first position, we have a user called "DBADMIN". This is a user we created to manage everything in the CDD. We make sure that whenever we create a new dictionary, DBADMIN is the user that occupies position 1. For position 2, we have a group called "ENG_APPL" that actually maintains this directory. The protections have been opened up for them (and for me on position 3). For position 4, the general users have only EPRS. These protections are important at this point because using DMU to create the directory and set the protections allows the users to access the domains, record definitions, and procedures using INHERITED privileges. Using the CDD's CDO utility will not allow this flexibility. When you decide to implement CDD Security features, you should also keep in mind that VMS file protections and file ownership have not changed! Just because you grant someone write access in the CDD doesn't necessarily mean that the person has write access on the RMS level. PHASE 2: The second phase of setting up the platform is performed at the DCL level. While this phase is not "critical", it adds functionality and ease of operation to the users. These commands (modified to suit your environment) should be added to your system startup: $ DEFINE/SYSTEM/NOLOG SIMONS_REPORTER "_CDD$TOP.SYSTEMS.SIMONS_REPORTER" $ SIMONS_REP*ORTER:==REPORT/PATH=SIMONS_REPORTER This shows how we defined a logical for the CDD directory we used as the platform. By creating a logical for the CDD path, this keeps users from wandering around the CDD and causing problems for other users. The symbol we created uses the same name as the logical. Few users would check to see if a symbol was also a logical. This symbol and logical were created at system startup. A command procedure executed at login time would look like: $ CDD_DICT := "DOESNT_EXIST" $ ACCOUNT = "''F$GETJPI("","ACCOUNT")'" $ ACCOUNT = F$EDIT(ACCOUNT,"TRIM")' $ USERNAME = "''F$GETJPI("","USERNAME")'" $ USERNAME = F$EDIT(USERNAME,"TRIM") . . . $ IF ACCOUNT .EQS. "CMPT_SER" THEN CDD_DICT := ISD$LIBRARY . . . $ DEFINE/NOLOG CDD$DEFAULT "_CDD$TOP.''CDD_DICT'.''USERNAME'" $ DEFINE/NOLOG MY_CDD "''F$TRNLNM("CDD$DEFAULT")'" Here is a key element in setting up this phase. The command procedure shown is accessed when a user first logs in. Most users don't know that this even exists. When we add a user to the system, we also add them a personal CDD subdirectory. This we have keyed to the "group" they belong to in the UAF. Members of the same UIC group will probably need to share procedures more than users from another UIC group. They will also be able to share common databases without opening the protections to world read. With that in mind, we define each individual user's CDD$DEFAULT and define the logical MY_CDD. This logical allows users to save a new DTR/DECREPORTER report to their personal CDD$DEFAULT without keying in the full CDD pathname. PHASE 3: Now that we have the CDD directory created, the protections set in the CDD, and the necessary symbols/logicals defined, it is time to populate the directory with domains, record definitions, and procedures. The first thing you do is look around the CDD for any existing DATATRIEVE procedures you want to use. These procedures are the ones that most users are comfortable with, have seen output from in the past, and probably cannot be reproduced through DECREPORTER. Here is how I extracted a sample DECREPORTER procedure and a sample DATATRIEVE procedure to disk. DMU> EXTRACT CDD$TOP.ISD$LIBRARY.JCOPENHAVER.USER_IMAGE_REPORT DECUS_DTR.BAK DMU> EXTRACT CDD$TOP.ISD$LIBRARY.JCOPENHAVER.USER_SEARCH DECUS_DECREPORTER.BAK DMU is the preferred way to extract a procedure. While DATATRIEVE can be used here, it is a good practice to use DMU while moving DECREPORTER and DATATRIEVE procedures. One of the nice things about DECREPORTER is that it produces DATATRIEVE code. While the two are not combined as a unified product now, they should be. If you look at code generated by DECREPORTER, you will notice several things that are not common to DATATRIEVE but are permitted by it. The SET SEMICOLON, the SET SEARCH, and the SET LOCK_WAIT are good examples of this. A typical report command file originally generated for DATATRIEVE would look like: ! DATATRIEVE PROCEDURE TO GENERATE USER IMAGE REPORTS ! READY DTR_CIS_DATA ! READY OBJECTS SHARED READ READY DTR_DATE READ ! ! ESTABLISH CURRENT COLLECTION ! PRINT "ESTABLISHING CURRENT COLLECTION" ! ! PRINT "BEGINNING COLLECTION, ETC...." ! ! FIND REPDAT IN DTR_CIS_DATA WITH DEPT_NO GT "099" ! SORT REPDAT BY DEPT_NO, USERNAME, OBJ_NAME ! ! DECLARE REIMB_CHARGE PIC 9(9)V99 COMPUTED BY CHOICE (PROJECT BETWEEN "1000" AND "9999") THEN SALES ELSE 0.0 END_CHOICE. DECLARE NONREIMB_CHARGE PIC 9(9)V99 COMPUTED BY CHOICE (PROJECT LT "1000") THEN SALES ELSE 0.0 END_CHOICE. DECLARE REIMB PIC 999V99. ! PRINT "BEGINNING USER IMAGE REPORT GENERATION" ! REPORT REPDAT ON SAC_QRSO:USER_IMAGE.RPT SET COLUMNS_PAGE = 132 SET REPORT_NAME = "COMPUTER RESOURCE ACCOUNTING"/"VAX COMPUTING SYSTEM"/" "/ "USER IMAGE REPORT" AT TOP OF PAGE PRINT REPORT_HEADER, SKIP, DATES FROM DTR_DATE, SKIP 3, COLUMN_HEADER AT BOTTOM OF REPORT PRINT SKIP 1, COL 21, ("REPORT TOTAL"), COL 50, TOTAL REIMB_CHARGE USING $,$$$,ZZZ.99, COL 70, TOTAL NONREIMB_CHARGE USING $,$$$,ZZZ.99, COL 90, TOTAL CONN_SEC/3600 USING ZZZ,ZZZ.99, COL 110, TOTAL CPU_SEC/10 USING ZZZ,ZZZ,ZZ9 END_REPORT ! PRINT "USER IMAGE REPORT GENERATION COMPLETED" ! FINISH ALL This sample DATATRIEVE procedure looks nothing like the DECREPORTER procedure in many ways. However, VAX/TPU will allow us to edit this procedure at the DCL level and disguise it as a DECREPORTER procedure. The procedure must be changed by adding at the beginning SET SEMICOLON; SET SEARCH; SET LOCK_WAIT; Each statement must be terminated with a semicolon. And SET NO SEMICOLON; SET NO SEARCH; FINISH ALL; must be appended to the end of the procedure. It is important to change anything in the procedure at this time. Once you have gotten DECREPORTER to accept a report procedure, you will not be able to edit the procedure after it is in the CDD and still have it accessible via DECREPORTER. With these changes, the procedure LOOKS like the DECREPORTER procedure now. All of the syntax for the two procedures is the same. Using DECREPORTER`s RDMU utility, we can now add this procedure into our new dictionary.
VAX DECreporter V2.1 Dictionary Management Utility MAINTENANCE SELECTIONS DOMAIN RECORD REPORT EXIT Utility ENTER SELECTION:
VAX DECreporter V2.1 Dictionary Management Utility SIMONS_REPORTER EXIT Utility ARNED;1 ARNED;2 PHS_PROJ_STD_2;1 PHS_PROJ_STD_3;1 PHS_STD_1;1 PROJECT_3709C;1 PROJECT_LISTING;1 TRS_BUS_DEV;1 TRS_DEPT_STD_1;1 TRS_DEPT_STD_2;1 TRS_DEPT_STD_3;1 TRS_DEPT_STD_4;1 TRS_IND_ALL_PROJ;1 TRS_IND_AREA_PROJ;2 TRS_IND_PROJ_AREA;1 TRS_PROJ_STD_1;1 TRS_PROJ_STD_2;1 Enter new REPORT name: decus_demo
VAX DECreporter V2.1 Dictionary Management Utility SIMONS_REPORTER EXIT Utility ARNED;1 ARNED;2 PHS_PROJ_STD_2;1 PHS_PROJ_STD_3;1 PHS_STD_1;1 PROJECT_3709C;1 PROJECT_LISTING;1 TRS_BUS_DEV;1 TRS_DEPT_STD_1;1 TRS_DEPT_STD_2;1 TRS_DEPT_STD_3;1 TRS_DEPT_STD_4;1 TRS_IND_ALL_PROJ;1 TRS_IND_AREA_PROJ;2 TRS_IND_PROJ_AREA;1 TRS_PROJ_STD_1;1 TRS_PROJ_STD_2;1 Enter REPORT command file: decus.tmp
VAX DECreporter V2.1 SIMONS_REPORTER EXIT Utility ARNED;1 ARNED;2 PHS_PROJ_STD_2;1 PHS_PROJ_STD_3;1 PHS_STD_1;1 PROJECT_3709C;1 PROJECT_LISTING;1 TRS_BUS_DEV;1 TRS_DEPT_STD_1;1 TRS_DEPT_STD_2;1 TRS_DEPT_STD_3;1 TRS_DEPT_STD_4;1 TRS_IND_ALL_PROJ;1 TRS_IND_AREA_PROJ;2 TRS_IND_PROJ_AREA;1 TRS_PROJ_STD_1;1 TRS_PROJ_STD_2;1 Recall report PROJECT_LISTING;1 (Y/N)? Y If you want to mix DATATRIEVE and DECREPORTER procedures in the same CDD directory, they would all show up when someone used the "Recall an Existing Report" option. However, if someone tried to access a DATATRIEVE procedure from DECREPORTER, they would get an error message.
@FILENAME. PHASE 4: The best feature of this platform is it's ability to have online help built into the record definition. DECREPORTER is quite nice in this aspect, where DATATRIEVE is not. If you have simple record definitions that exist in the CDD, I suggest you use RDMU to recreate them and incorporate the helps at that point. However, it almost never works out that way. Here is an abbreviated record definition that allows users to see the "helps" added in the record. All the user does is press . DEFINE RECORD TIME_REPORTING_SYSTEM_REC DESCRIPTION IS /* This is the record for the Time Reporting System */. TRS_DOMAIN_REC STRUCTURE. /* week ending dd/mm/yy */ WEEK_ENDING DATATYPE IS TEXT SIZE IS 8 CHARACTERS PICTURE FOR DATATRIEVE IS "X(8)" QUERY NAME FOR DATATRIEVE IS "WEND". /* Project number */ PROJECT DATATYPE IS TEXT SIZE IS 5 CHARACTERS PICTURE FOR DATATRIEVE IS "X(5)". /* Area number */ AREA DATATYPE IS TEXT SIZE IS 3 CHARACTERS PICTURE FOR DATATRIEVE IS "X(3)". /* Hours project to date */ HOURS_PROJECT_TO_DATA DATATYPE IS RIGHT SEPARATE NUMERIC SIZE IS 7 DIGITS SCALE -1 PICTURE FOR DATATRIEVE IS "S9(6)V9(1)" QUERY NAME FOR DATATRIEVE IS "HPYTD" EDIT STRING FOR DATATRIEVE IS "-Z(5)9.9". END TRS_DOMAIN_REC_STRUCTURE. END TIME_REPORTING_SYSTEM_REC RECORD. If you look at this record definition, you will see how "helps" look in the actual record definition itself. When a user accesses this record definition from DECREPORTER, all he needs to do is press and the help for that particular field will appear on the screen and help him determine if he wants to select it. If you have an existing DECREPORTER record definition that you want to move to the platform, follow these steps exactly: 1. Enter DMU and set your default over to the dictionary that holds the record definition (if it is different than your CDD$DEFAULT). 2. Type "LIST" to make sure that the record definition is out there. Type DMU> EXTRACT/RECORD record_name out_file_name. If the record definition is a DATATRIEVE definition, you can edit it at this point and add any help messages you want. 3. The ONLY way to get this record back into the CDD with the help messages intact is to follow these step EXACTLY: a. $define cdd$default simons_reporter b. $CDDL out_file_name 4. Re-enter DMU and type DMU> LIST/FULL record_name on the record and check the record for accuracy. 5. Reset your CDD$DEFAULT to its correct dictionary path. PHASE 5: Earlier we covered the way you can set protections using the CDD. There are a few things that should be added here. For practical purposes, you can consider that the CDD protections sit on top of the DCL protections. That is, even if a file has a DCL world read protection on it, they cannot access it via the CDD unless you set it up that way. On the other hand, just because you allow them to access something via the CDD doesn't necessarily mean that DCL will permit it. This is a strong security feature and should not be overlooked. An example of this is a personnel database containing salary information. A manager may need the information there, but not want the clerks to have access to it. Even if the clerks had other valid procedures they needed to run from the platform, the manager could eliminate anyone from snooping around by restricting the access to the file at DCL level. PHASE 6: Earlier, we covered how to move the altered DATATRIEVE procedures, DECREPORTER reports, domains, and record definitions. We ended up with a platform that was populated with some procedures, but not everything that some users may need. As the person creating this platform, you need to have a flexibility that will allow users to create their own reports from the platform but not clutter it up with them. One of the first things we did was create a logical called "MY_CDD". This logical will allow users to enter the platform, create a new report to their specifications and save it to their personal CDD directory.
[P1;P2;P3;P4:P5;P6| where P1 is 0 for the absolute position or 1 for the relative position, P2 is the x starting position in thousands of an inch, P3 is the y starting position in thousands of an inch, P4 is the horizontal length, P5 is the vertical height, and P6 is the pattern. The default pattern for black is 65535(10) or 1111111111111111(2) grey is 43690(10) or 1010101010101010(2) white is 00000(10) or 0000000000000000(2). The Talaris escape sequence to save the current horizontal position in save area 1 is [1;1 x and the sequence to restore the current horizontal position from save area 1 is [0;1 x The complete procedure to drive the Talaris printer is: DEFINE PROCEDURE PRINT_SURVEY_BAR_REPORT READY CURCC_DOM SHARED DECLARE CURCC1 PIC 999. DECLARE CURCC2 PIC 999. DECLARE NEMPCC1 PIC 9999. DECLARE NEMPCC2 PIC 9999. DECLARE NEMPCC3 PIC 9999. DECLARE CURCCTITLEX PIC X(60). DECLARE RPTYPEX PIC X. FOR FIRST 1 CURCC_DOM BEGIN CURCC1 = CUR_CC1 CURCC2 = CUR_CC2 RPTYPEX = RPT_TYPE NEMPCC1 = NUMCC1 NEMPCC2 = NUMCC2 NEMPCC3 = NUMCC3 CURCCTITLEX = CURCCTITLE END READY SURVEY_REP_ABC SHARED DECLARE THEME_A_FAV COMPUTED BY THEME VIA THEME_AFAV_TABLE.M DECLARE THEME_ORDER COMPUTED BY IF ORDER = 0 THEN 999 ELSE AFAV . DECLARE TWIDE PIC 9999. TWIDE = 4000 FIND ALL SURVEY_REP_ABC WITH THEME LT 14 SORT BY DESC THEME_A_FAV,ASC THEME,DESC THEME_ORDER REPORT ALL CURRENT ON SURBARRPT SET COLUMNS_PAGE=250 ! ! Each record prints three bars (the third bar does not print if CFAV missing) ! of comparative survey data (AFAV,BFAV, AND CFAV are favorable responses) ! (AUN ... unfavorable), the middle segment is wishy washy responses. ! The three bars are comparing a parent group with a specific group and ! with different year ! ! Each bar has three bar segments that have total width in inches of TWIDE ! with the first segment being AFAV (value 0-100) percent of total on left ! right hand segment AUNF ( " ) " of total on right ! middle segment (100 - AFAV - AUNF) with different shading ! ! Pad each bar with enough blanks so that the t(145) folds each bar and ! left justifies in the proper column. ! ! The [0;1 x recalls beginning (left) position of bar requiring ! a string of spaces to position text that is to appear at right of bar ! PRINT SKIP 3,COL 1,FN$STR_EXTRACT(ITEM VIA ITEM_TABLE,1,6)(-) USING X(6), COL 8,FORMAT FN$STR_EXTRACT(ITEM VIA ITEM_BIG_TABLE,7,239) USING X(239)||""(-) USING T(45), COL 60,("A " | AFAV | " [1;1 x[1;0;0;"| FN$NINT(TWIDE*(AFAV/100.00)) || ";65436;|[1;" | FN$NINT(TWIDE*(AFAV/100.00)) || ";0;" | FN$NINT(TWIDE*((100.0 - AFAV - AUNF)/100.00)) || ";65436;2048|[1;" | FN$NINT(TWIDE*((100.0 - AFAV - AUNF)/100.00))|| ";0;" | FN$NINT(TWIDE*(AUNF/100.00)) || ";65436;43690|[0;1 x {MANY SPACES HERE} "| AUNF | " B " | BFAV | " [1;1 x[1;0;0;"| FN$NINT(TWIDE*(BFAV/100.00)) || ";65436;|[1;" | FN$NINT(TWIDE*(BFAV/100.00)) || ";0;" | FN$NINT(TWIDE*((100.0 - BFAV - BUNF)/100.00)) || ";65436;2048|[1;" | FN$NINT(TWIDE*((100.0 - BFAV - BUNF)/100.00))|| ";0;" | FN$NINT(TWIDE*(BUNF/100.00)) || ";65436;43690|[0;1 x {MANY SPACES HERE} "| BUNF | IF CFAV = " " AND CUNF = " " THEN "" ELSE " C " | CFAV | " [1;1 x[1;0;0;"| FN$NINT(TWIDE*(CFAV/100.00)) || ";65436;|[1;" | FN$NINT(TWIDE*(CFAV/100.00)) || ";0;" | FN$NINT(TWIDE*((100.0 - CFAV - CUNF)/100.00)) || ";65436;2048|[1;" | FN$NINT(TWIDE*((100.0 - CFAV - CUNF)/100.00))|| ";0;" | FN$NINT(TWIDE*(CUNF/100.00)) || ";65436;43690|[0;1 x"| " "| CUNF || "" ) USING T(164) AT TOP OF PAGE PRINT SKIP 7,COL 42, 'SURVEY: HARRIS BANK EMPLOYEE OPINION SURVEY', SKIP 3, COL 3, 'ITEM REPORT: '|CURCCTITLEX(-) ,SKIP,COL 45, ' SUBGROUP',COL 76,'SYMBOL N', COL 45, ' --------',COL 76,'------ -',SKIP, COL 45,CHOICE RPTYPEX = "D" THEN "GROUP " RPTYPEX = "G" THEN "DEPARTMENT" RPTYPEX = "S" THEN "DIVISION" ELSE "???" END_CHOICE | " " | FORMAT CURCC2 USING ZZ9 | " (1988)" , COL 79,"A " | FORMAT NEMPCC2 USING ZZZ9 ,SKIP, COL 45,CHOICE RPTYPEX = "D" THEN "DIVISION" RPTYPEX = "G" THEN "GROUP " RPTYPEX = "S" THEN "SECTION " ELSE "???" END_CHOICE | " " | FORMAT CURCC1 USING ZZ9 | " (1988)", COL 79,"B " | FORMAT NEMPCC1 USING ZZZ9 ,SKIP, COL 45,CHOICE RPTYPEX = "D" THEN "DIVISION" RPTYPEX = "G" THEN "GROUP " RPTYPEX = "S" THEN "SECTION " ELSE "???" END_CHOICE | " " | FORMAT CURCC1 USING ZZ9 | " (1986)", COL 79,"C " | FORMAT NEMPCC3 USING ZZZ9 ,SKIP 4, COL 6, THEME VIA THEME_TABLE(-) USING T(73), COL 75,"% FAVORABLE % NEUTRAL %UNFAVORABLE",SKIP, COL 70, "[1;0;0;"| FN$NINT(TWIDE*.333) || ";65436;|[1;" | FN$NINT(TWIDE*.333) || ";0;" | FN$NINT(TWIDE*.333) || ";65436;2048|[1;" | FN$NINT(TWIDE*.333)|| ";0;" | FN$NINT(TWIDE*.333) || ";65436;43690|" AT BOTTOM OF THEME PRINT NEW_PAGE END_REPORT END_PROCEDURE The report looks like: [Editor's note: Since the hardcopy of the newsletter is produced on a Postscript printer, it is not possible to exactly reproduce the Talaris output. Also the report below has been narrow to 80 columns rather than the original 132 column report.]] SURVEY: HARRIS BANK EMPLOYEE OPINION SURVEY ITEM REPORT: ELECTRONIC PROCESSING DIVISION SUBGROUP SYMBOL N ------- ------ - GROUP 401 (1988) A 448 DIVISION 450 (1988) B 98 DIVISION 450 (1986) C 59 %FAVORABLE %NEUTRAL %UNFAVORABLE Q41: USEFULNESS ... aaaaaaaaaaaaaaaxxxxxxxxxxxxxxxaaaaaaaaaaaaaaa 41D. Immediate ... A 74 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaxxxxxxxxxaaa B 77 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaxxxxxxxxxaa . . . 41E. Co-workers ... A 53 aaaaaaaaaaaaaaaaaaaaaaaxxxxxxxxxxxxxaaaaaaaaa B 49 aaaaaaaaaaaaaaaaaaaaaxxxxxxxxxxxxxxxxaaaaaaaa . . . With this procedure, John was able to give better output than the outside consulting firm and run the Talaris printer at full speed of 16 pages per minute. Part 3 of Wombat Magic will continue next month