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. <FIGURE TITLE: Main RDMU Menu> VAX DECreporter V2.1 Dictionary Management Utility MAINTENANCE SELECTIONS DOMAIN RECORD REPORT EXIT Utility ENTER SELECTION: <FIGURE TITLE: Specification of Report Name in RDMU> 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 <FIGURE TITLE: Specification of Report Command File Name to RDMU> 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 <FIGURE TITLE: RDMU Screen Loading the Report Selection VAX DECreporter V2.1 Dictionary Management Utility SIMONS_REPORTER.DECUS_DEMO SET SEMICOLON; SET SEARCH; ! DATATRIEVE PROCEDURE TO GENERATE USER IMAGE REPORTS ! READY DTR_CIS_DATA; ! READY OBJECTS SHARED READ READY DTR_DATE READ; ! More... Storing Dictionary Object At this point, if you enter SIMONS_REPORTER from the DCL level, you will see the "new" report by accessing the "Recall an Existing Report" option. If selected, the report should run providing that all necessary changes have been made. <FIGURE TITLE: User Recalling an Existing Report> 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. <FIGURE TITLE: Error Message Generated when Trying to Access a DATATRIEVE Report using DECREPORTER VAX DECreporter SIMONS_REPORTER EXIT DECreporter ARNED;1 ARNED;2 DECUS_DEMO;1 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 Select the report to be recalled: DECUS_DEMO;1 has been created by Datatrieve. Please use Datatrieve to Process this Report Unless you have complicated CDD domain definitions, it may be easier to simply recreate them in the new directory using RDMU. If you want to move a domain definition, the easiest method in this case, is to use DATATRIEVE to: 1. extract the domain to a DCL file 2. edit the file if necessary 3. reload using DATATRIEVE DTR>@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 <PF4>. 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 <PF4> 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. <FIGURE TITLE: Illustration of Person Saving a Report to MY_CDD.Whatever --------------------------------------------------------Selection Criteria--------------------------------------------------------- SIMONS_REPORTER.PROJECT_HISTORY_SYSTEM;2 PROJECT DEPT AREA ACT_CODE HOURS_PROJECT_TO_DATE Name of this report: my_cdd.decus_demo This report can be accessed directly from the user's CDD directory by using either DATATRIEVE or DECREPORTER. It will retain all pointers to the platform, its domains and record definitions but will not clutter the platform up with a report only one person will use. DECREPORTER has some limits that DATATRIEVE doesn't. For example, DATATRIEVE will allow you to create a report over 132 characters wide. DECREPORTER alone will not. However, you can create a "SHELL" from DECREPORTER and modify it to your specific needs. A typical report procedure created by DECREPORTER looks like: SET SEMICOLON; SET SEARCH; SET LOCK_WAIT; SET DICTIONARY CDD$TOP.PROD$LIBRARY.QUANTUM; READY DTR_CIS_DATA SHARED READ; REPORT DTR_CIS_DATA ON * ."the report output device and filespec "; SET COLUMNS_PAGE = 132; SET LINES_PAGE = 55; SET REPORT NAME = "DECUS DEMO"; PRINT COL 2, NODE ("NODE") USING XXXXXX, COL 9, PROJ_NO ("PROJECT") USING XXXX, COL 17, PROJ_SUF ("PROJECT"/"SUFFIX") USING X, COL 25, DEPT_NO ("DEPARTMENT"/"NUMBER") USING XXX, COL 36, USERNAME ("USERNAME") USING XXXXXXXXXXXXXXXX. COL 51, OBJ_NAME ("OBJECT"/"NAME") USING XXXXXXXXXXXXXXXX, COL 68, CONN_SEC ("CONNECT"/"TIME") USING XXXXXXXX, COL 77, CPU_SEC ("CPU"/"TIME"/"SECONDS") USING XXXXXXXX, COL 90, PAGE_FAULTS ("PAGE"/"FAULTS") USING XXXXXXXX, COL 99, DIRECT_IO ("DIRECT"/"IO") USING XXXXXXXX, COL 108, BUFF_IO ("BUFFERED"/"IO") USING XXXXXXXX, COL 117, PRINT_PAGES ("PRINTED"/"PAGES") USING XXXXX, COL 125, SALES ("SALES") USING XXXXXXXX ; AT BOTTOM OF REPORT PRINT SKIP 2 ; END_REPORT; SET NO SEMICOLON; SET NO SEARCH; FINISH ALL; The limit on this report is 132 columns wide, but my specific needs require a report that goes beyond that. I know which field I want to add and the size that the report should be. So it can be "fixed" by changing from SET COLUMNS_PAGE = 132; to SET COLUMNS_PAGE = 150; and replacing COL 125, SALES ("SALES") USING XXXXXXXX; with COL 125, SALES ("SALES") USING XXXXXXXX, COL 136, AUTHORIZATION_CODE ("AUTHORIZATION"/"CODE") USING XXXXXXXXXX; This procedure has been modified to allow a report limit of 150. We defined a form that will allow our LN03 to print it. I also added a field to the procedure. One way to do this is to create a field at the end of the report and replace it with the "real" field. After the procedure has been edited to your satisfaction, enter RDMU and add the report from there. Remember to use DECREPORTER syntax for any changes. PHASE 7: The final phase is to let the users know how to use the platform. It seems like it would be easy for anyone to use, but users can be quite hesitant to try something new. The easiest way for everyone to learn about it is send a memo around with detailed instructions. There are several drawbacks to this method. The first is that many people never read their memos. They will glance at it and throw it in the trash. Another problem with memos is that it is hard to target the memo to the people who will actually use the platform. Another approach is to hold a "brown bag seminar" to show them how the platform really works. After the demonstration, you can pass out the instructions to those who attend. You might hold several of them to accommodate those who may have missed the first "brown bag". If you have the personnel that can do it, have someone go around to each of the users and show them individually how to use the platform and customize their own reports. This insures that you get the necessary feedback from the users on how to improve the procedures and the user documentation. ---------------------------------------------------------------- Dear Wombat Wizard ---------------------------------------------------------------- Dear Wombat Wizard: I have an indexed data file approaching 15,000 records. The key is 6 characters long. The first character is alphanumeric; the remaining 5 are numeric only. In other words, some of the keys have an alphabetic prefix. What I need to do is change the prefix to a suffix. The objective is a 6-character key with the first 5 characters numeric and the sixth alphanumeric. What I need is some ideas as to how to convert the existing records (probably several hundred of them) from the A99999 form to the 99999A form without doing each record manually. Signed, Need Some Keys Changed Dear Changed: Assuming that the records are located in an RMS file (even if it is in Rdb), it still shouldn't be too hard. I would use DATATRIEVE, naturally! I am also assuming that the key is the primary key, which means that it cannot be changed. In order to change the primary key, you must delete the record and reenter it with the new key value. If MOST of the records need to be altered, I would consider just setting up a new data file and transfer over each record, making the conversion in the key field as necessary. If less than 30% (a fairly arbitrary number) of the record need to be changed, then I would just do it in the same file. Take each record, look at the key to see if it begins with an alphanumeric, if it does, then do a store to a new record with the appropriate change to the key field (put the alpha portion on the end instead of the front). If storing in the same file then delete the original record. The record definition for the data file could be DEFINE RECORD FOO-RECORD USING 01 FOO-REC. 03 KEY-FIELD PIC X(6). 03 REST-OF-RECORD PIC X(n). ; Then the statements and commands to restructure those particular records which begin with an alpha could look like: READY FOO AS OLD SHARED WRITE READY FOO AS NEW SHARED WRITE FOR OLD WITH KEY-FIELD NOT BETWEEN "0" AND "999999" BEGIN STORE NEW USING BEGIN KEY-FIELD = FN$STR_EXTRACT(KEY-FIELD,2,5)|FN$STR_EXTRACT(KEY-FIELD,1,1) REST-OF-RECORD = REST-OF-RECORD END ERASE END There are several other ways you could do this. One of the more interesting is by using a group field in two domains. The old record would look like 01 FOO-REC. 03 KEY-FIELD. 05 ALPHA-CHARACTER PIC X. 05 NUMERAL-CHARACTERS PIC X(5). 03 REST-OF-RECORD PIC X(n). ; and the new record would look like 01 FOO-REC. 03 KEY-FIELD. 05 NUMERAL-CHARACTERS PIC X(5). 05 ALPHA-CHARACTER PIC X. 03 REST-OF-RECORD PIC X(n). ; Note the change in order of the fields. After you have restructured your data file, you will most certainly want to recover the space in the deleted records with a CONVERT/RECLAIM and re-optimize the file by the well known steps ANALYZE/FDL, EDIT/FDL, and CONVERT/FDL which are described in your RMS tuning guide. One of DATATRIEVE's most useful features is its ability to easily restructure data. Signed, The Wombat Wizard (LJ&SC&JG) ---------------------------------------------------------------- The 4GL Problem for New Orleans Winston Tellis, Problem Session Coordinator ---------------------------------------------------------------- At a meeting of DTR/4GL SIG sponsored Working Group Chairs and Counterparts at the 1989 Spring Symposia in Atlanta, Working Groups expressed an interest in cooperating in one or more symposia presentations. One suggested activity was that each 4GL Working Group present a solution to the same problem. Since the logistics for such a symposia presentation would require some significant commitments by members of the working groups, it was decided that such a presentation could not be made in Anaheim in the Fall of 1989 but could be accomplished in New Orleans in the Spring of 1990. Each of the DTR/4GL SIG Working Groups and DATATRIEVE is invited to select a representative to present a solution to the problem which follows at the Spring 1990 DECUS Symposium in New Orleans. There will be one and only one presentation from each participating 4GL. The representative must be chosen and the DTR/4GL SIG Steering Committee notified by the end of the Anaheim Symposia so that the appropriate amount of time may be scheduled for New Orleans. The order of presentations in New Orleans will be determined by a random drawing; each presenter will have exactly the same amount of time to present their solutions. The problem is a "People Database" browse problem. The record layout is as follows: id number 7 digit numeric, primary key, no dups last name 15 characters secondary key (dups allowed) first name 10 characters middle initial 1 character title of address (Mr., Ms., Mrs., Dr., etc) seniority (Jr., Sr., II, III etc) address including city, state, and zip soundex of last name secondary key (dups allowed) You are to write and describe an application in which a user may enter the id number, or last name, or part of last name, or the soundex of the last name. If the entry selects a unique record, the user gets to look at the record to confirm that it is the desired record. If the entry is not unique, the user gets records to browse through in sort order of last name, first name, and middle initial (either by paging or scrolling through a list both forward and backwards) to select the desired record. The browse display will include the id number, the full name with title and suffix, and the city. The data base is large; there are more than 10,000 records. The application must be prepared to deal with at least 400 potential records in the browse (approximately 20 screens of 20 records each). There is no restriction on the programming technique and whether or not you have to link to another language (3GL) to execute a particular routine. For those 4GLs not having a built-in Soundex algorithm, you may use the MACRO routine described in Bart Lederman's article in the March 1989 issue of the Newsletter, Volume 4, Number 7, pages DTR-5 to DTR-12. Comparing how each product approaches the problem should be most interesting. ---------------------------------------------------------------- Wombat Magic, Spring 1989 - Part 2 Session Co-Chairs: Dana Schwartz, DOD and Bert Roseberry, U. S. Coast Guard, Washington, DC Session Editor: Joe H. Gallagher, Ph. D., 4GL Solutions, Overland Park, KS ---------------------------------------------------------------- Editor's note: The following is Part 2 of a highly edited transcription of the Wombat Magic Session at the 1989 Spring DECUS Symposium in Atlanta, Georgia, which occurred on May 11, 1989. Part 1 appeared in the July 1989 newsletter. Material which was presented on transparencies has been merged into the oral presentation. An attempt has been made to convey both the technical content of the Magic Session as well as the humor, covert intellectual swaggering, and the spirited interchange of the presentations. Material which appears in the text within square brackets [] has been added by the editor in an attempt to improve the understandability of this very exciting Magic Session. The material presented here is not presented in the same order as it occurred in the session. John Putnam, Harris Trust and Savings Bank, Chicago, IL John described a problem in which he was asked to produce approximately 2400 pages of text and horizontal bar charts in 2 week window. The report had to effectively match the report format and presentation quality of prototype reports produced by outside consultants. And the report had to be done in-house and in a timely fashion. The problem is that mixed test and bar graphs using Tellagraph and a LN03 laser printer to 12 minutes per page. [A quick calculations will tell that it would take more than 19 days to print all the reports.] So John's obvious answer to the problem was to use the DATATRIEVE Report Writer (and his Talaris Printer). The report had to made horizontal bar graphs which represented the percent of favorable, neutral, and unfavorable responses to an in-house questionnaire. For each record, two or three graphs needed to be produced -- for group A and B and optionally group C. The "trick" to the problem was fully understanding and using the escape sequences of the Talaris 1590 printer. The Talaris native function to plot rulers has the command format: <ESC>[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 <ESC>[1;1 x and the sequence to restore the current horizontal position from save area 1 is <ESC>[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 <ESC>[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 | " <ESC>[1;1 x[1;0;0;"| FN$NINT(TWIDE*(AFAV/100.00)) || ";65436;|<ESC>[1;" | FN$NINT(TWIDE*(AFAV/100.00)) || ";0;" | FN$NINT(TWIDE*((100.0 - AFAV - AUNF)/100.00)) || ";65436;2048|<ESC>[1;" | FN$NINT(TWIDE*((100.0 - AFAV - AUNF)/100.00))|| ";0;" | FN$NINT(TWIDE*(AUNF/100.00)) || ";65436;43690|<ESC>[0;1 x {MANY SPACES HERE} "| AUNF | " B " | BFAV | " <ESC>[1;1 x<ESC>[1;0;0;"| FN$NINT(TWIDE*(BFAV/100.00)) || ";65436;|<ESC>[1;" | FN$NINT(TWIDE*(BFAV/100.00)) || ";0;" | FN$NINT(TWIDE*((100.0 - BFAV - BUNF)/100.00)) || ";65436;2048|<ESC>[1;" | FN$NINT(TWIDE*((100.0 - BFAV - BUNF)/100.00))|| ";0;" | FN$NINT(TWIDE*(BUNF/100.00)) || ";65436;43690|<ESC>[0;1 x {MANY SPACES HERE} "| BUNF | IF CFAV = " " AND CUNF = " " THEN "" ELSE " C " | CFAV | " <ESC>[1;1 x<ESC>[1;0;0;"| FN$NINT(TWIDE*(CFAV/100.00)) || ";65436;|<ESC>[1;" | FN$NINT(TWIDE*(CFAV/100.00)) || ";0;" | FN$NINT(TWIDE*((100.0 - CFAV - CUNF)/100.00)) || ";65436;2048|<ESC>[1;" | FN$NINT(TWIDE*((100.0 - CFAV - CUNF)/100.00))|| ";0;" | FN$NINT(TWIDE*(CUNF/100.00)) || ";65436;43690|<ESC>[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, "<ESC>[1;0;0;"| FN$NINT(TWIDE*.333) || ";65436;|<ESC>[1;" | FN$NINT(TWIDE*.333) || ";0;" | FN$NINT(TWIDE*.333) || ";65436;2048|<ESC>[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