Loading...
Searching...
No Matches
getdata.sas
Go to the documentation of this file.
1/**
2 @file getdata.sas
3 @brief Returns a dataset to the editor front end
4 @details
5
6 <h4> Service Inputs </h4>
7
8 <h5> SASCONTROLTABLE </h5>
9 |LIBDS:$41.|FILTER_RK:$5.|
10 |---|---|
11 |DC258467.MPE_X_TEST|-1|
12
13 <h4> Service Outputs </h4>
14 <h5> sasdata </h5>
15 <h5> sasparams </h5>
16 Contains info on the request. One row is returned.
17 @li CLS_FLG - set to 0 if there are no CLS rules (everything editable)
18 else set to 1 (CLS rules exist)
19 @li ISMAP - set to 1 if the target DS is an excel map target, else 0
20
21 <h5> approvers </h5>
22 <h5> dqrules </h5>
23 <h5> dqdata </h5>
24 <h5> cols </h5>
25 Contains column level attributes.
26 @li NAME - column name
27 @li LABEL - var label. https://core.sasjs.io/mp__getcols_8sas.html
28 @li FMTNAME - derived format. https://core.sasjs.io/mp__getcols_8sas.html
29 @li DDTYPE - derived dropdown. C=CHARACTER, N=NUMERIC, else DATE / TIME /
30 DATETIME. https://core.sasjs.io/mp__getcols_8sas.html
31 @li CLS_RULE - values include:
32 - EDIT - the column is editable
33 - READ - the column should be readonly
34 - HIDE - the column should be hidden
35 @li memlabel
36 @li desc- augmented with MPE_DATADICTIONARY if exists, else label
37 @li longdesc - from MPE_DATADICTIONARY
38 @li coltype - front-end column formatting spec
39
40
41 <h5> maxvarlengths </h5>
42 <h5> xl_rules </h5>
43 <h5> query </h5>
44
45 <h5> versions </h5>
46 history of DC versions for this particular table
47
48
49 <h4> SAS Macros </h4>
50 @li dc_assignlib.sas
51 @li dc_casload.sas
52 @li dc_getgroupmembers.sas
53 @li mf_existvar.sas
54 @li mf_getattrn.sas
55 @li mf_getvarlist.sas
56 @li mf_existds.sas
57 @li mf_getquotedstr.sas
58 @li mf_getuser.sas
59 @li mf_nobs.sas
60 @li mf_verifymacvars.sas
61 @li mf_wordsinstr1butnotstr2.sas
62 @li mp_abort.sas
63 @li mp_cntlout.sas
64 @li mp_getcols.sas
65 @li mp_getmaxvarlengths.sas
66 @li mp_validatecol.sas
67 @li mpe_accesscheck.sas
68 @li mpe_columnlevelsecurity.sas
69 @li mpe_dsmeta.sas
70 @li mpe_getlabels.sas
71 @li mpe_getversions.sas
72 @li mpe_filtermaster.sas
73 @li mpe_runhook.sas
74
75 @version 9.2
76 @author 4GL Apps Ltd
77 @copyright 4GL Apps Ltd. This code may only be used within Data Controller
78 and may not be re-distributed or re-sold without the express permission of
79 4GL Apps Ltd.
80
81**/
82
83%mpeinit()
84
85/**
86 * Validate inputs
87 */
88data work.intest;
89 length filter_rk 8;
90 set work.SASCONTROLTABLE;
91
92 /* validate filter_rk */
93 if filter_rk le 0 then filter_rk=-1;
94
95 call symputx('orig_libds',upcase(libds));
96
97 is_fmt=0;
98 if substr(cats(reverse(libds)),1,3)=:'CF-' then do;
99 libds=scan(libds,1,'-');
100 putlog "Format Catalog Captured";
101 is_fmt=1;
102 libds='work.fmtextract';
103 call symputx('libds',libds);
104 end;
105 call symputx('is_fmt',is_fmt);
106 putlog (_all_)(=);
107
108 /* validate libds */
109 %mp_validatecol(LIBDS,LIBDS,is_libds)
110
111 if is_libds=0 then do;
112 putlog 'ERR' 'OR: Invalid libds:' libds;
113 stop;
114 end;
115 else do;
116 call symputx('filter_rk',filter_rk);
117 call symputx('libds',libds);
118 end;
119 output;
120 stop;
121run;
122
123%mp_abort(iftrue= (%mf_nobs(work.intest)=0)
124 ,mac=&_program
125 ,msg=%str(Some err with service inputs)
126)
127
128%mp_abort(
129 iftrue=(%mf_verifymacvars(libds filter_rk)=0)
130 ,mac=&_program
131 ,msg=%str(Missing: libds filter_rk)
132)
133
134/* export format catalog */
135%mp_cntlout(
136 iftrue=(&is_fmt=1)
137 ,libcat=&orig_libds
138 ,fmtlist=0
139 ,cntlout=work.fmtextract
140)
141
142/* stream back meta info, further calls will return col metadata and actual data
143*/
144%let libref=%upcase(%scan(&libds,1,.));
145%let dsn=%upcase(%scan(&libds,2,.));
146%dc_assignlib(WRITE,&libref)
147%dc_casload(&libds)
148
149/**
150 * First check user has access permission to edit the table
151 */
152%put checking access;
153%let user=%mf_getuser();
154%mpe_accesscheck(&orig_libds,outds=mw_auth,user=&user,access_level=EDIT)
155
156
157%mp_abort(iftrue= (%mf_getattrn(work.mw_auth,NLOBS)=0)
158 ,mac=mpestp_getdata.sas
159 ,msg=&user is not authorised to edit &orig_libds %trim(
160 )in the &mpelib..MPE_SECURITY table
161)
162
163%mp_abort(iftrue= ( %mf_existds(libds=&libds) ne 1)
164 ,mac=mpestp_getdata.sas
165 ,msg=dataset &libds does not exist!!
166)
167
168%mp_abort(iftrue= (&syscc ne 0)
169 ,mac=&_program..sas
170 ,msg=%str(syscc=&syscc at line 60 )
171)
172
173
174%global loadtype var_txfrom var_txto var_processed filter_text pk coltype
175 sortpk;
176
177%put getting table attributes;
178proc sql noprint;
179select upcase(loadtype)
180 ,var_txfrom,var_txto
181 ,var_busfrom,var_busto
182 ,var_processed,rk_underlying,buskey
183 ,coalesce(rk_underlying,buskey)
184 ,pre_edit_hook
185 ,case when missing(rk_underlying) then buskey else rk_underlying end
186 into: loadtype,:var_txfrom,:var_txto
187 ,:var_busfrom ,:var_busto
188 ,:var_processed,:rk_underlying,:buskey, :sortPK, :pre_edit_hook,:pk
189 from &mpelib..mpe_tables
190 where &dc_dttmtfmt. lt TX_TO
191 and upcase(dsn)="%scan(&orig_libds,2,.)"
192 and upcase(libref)="%scan(&orig_libds,1,.)";
193
194%put preparing filter query:;
195%mpe_filtermaster(EDIT,&orig_libds,
196 dclib=&mpelib,
197 filter_rk=&filter_rk,
198 outref=filtref,
199 outds=work.query
200)
201
202%macro mpestp_getdata();
203 %if not %symexist(DC_MAXOBS_WEBEDIT) %then %do;
204 %put NOTE:;%put NOTE- DC_MAXOBS_WEBEDIT not found!;
205 %put NOTE- Please add to &mpelib..MPE_CONFIG table;
206 %put NOTE-;%put NOTE-;
207 %global DC_MAXOBS_WEBEDIT;
208 %let DC_MAXOBS_WEBEDIT=500;
209 %end;
210 /* for tables which use RKs/SKs then we just expose the business key to
211 users - this lets uploads be sent to multiple environments (with
212 potentially different RK/SK values for the same business key).
213 Note that the config table has the RK column in the buskey field in
214 this scenario. */
215 %if %length(&rk_underlying)>0 %then %let drop_rk=&buskey;
216 %else %let drop_rk=;
217
218 /* always remove the PROCESSED_DTTM column, if it exists */
219 %if %length(&var_processed)=0 %then %do;
220 %if %mf_existvar(&libds,PROCESSED_DTTM)>0 %then
221 %let var_processed=PROCESSED_DTTM;
222 %end;
223
224 /**
225 * Now get the slice of the actual table
226 */
227 options obs=10000;
228
229 %if &loadtype=BITEMPORAL %then %do;
230 data out (drop=&var_txfrom &var_txto &var_processed &drop_rk );
231 _____DELETE__THIS__RECORD_____="No";
232 set &libds;
233 where %inc filtref;;
234 run;
235 proc sort data=out;
236 by &pk &var_busfrom;
237 run;
238 data out;
239 set out;
240 by &pk &var_busfrom;
241 if last.%scan(&pk,-1);
242 run;
243 %end;
244 %else %do;
245 data out (drop=&var_txfrom &var_txto &var_processed &drop_rk);
246 _____DELETE__THIS__RECORD_____="No";
247 set &libds;
248 where %inc filtref;;
249 run;
250 %end;
251 options obs=max;
252 %mp_abort(iftrue= (&syscc ne 0)
253 ,mac=&_program
254 ,msg=%str(Issue with filtering (line 165) )
255 )
256
257 options obs=&DC_MAXOBS_WEBEDIT;
258 %let sortpk=%sysfunc(coalescec(&sortpk &var_busfrom,_ALL_));
259 proc sort data=work.out; by &sortPK; run;
260 options obs=max;
261
262 %mpe_runhook(PRE_EDIT_HOOK)
263
264 %let obscnt=%mf_getattrn(work.out,NLOBS);
265 %mp_abort(iftrue=(&obscnt>&DC_MAXOBS_WEBEDIT)
266 ,mac=&_program
267 ,msg=Table is too big (&obscnt rows) - please filter and try again!
268 )
269
270
271 /* order delete var and pk fields at start of table */
272 %let sourcevars=%mf_wordsInStr1ButNotStr2(
273 Str1=%mf_getvarlist(work.out)
274 ,Str2= _____DELETE__THIS__RECORD_____ &pk
275 );
276 %put sourcevars=&sourcevars;
277 data outdata;
278 /* delete & pk fields come first */
279 attrib _____DELETE__THIS__RECORD_____ &pk label='';
280 /* keep remaining variable order */
281 %if %length(&sourcevars)>0 %then %do;
282 attrib &sourcevars label='';
283 %end;
284 _____DELETE__THIS__RECORD_____="No ";
285 %if %mf_nobs(work.out)=0 %then %do;
286 /* send empty row if empty table to help with hot rendering */
287 output;
288 %end;
289 set work.out ;
290 run;
291
292
293
294 /* get list of variables and their formats */
295 proc contents noprint data=outdata
296 out=vars(keep=name type length varnum format: label);
297 run;
298
299 proc sort;
300 by varnum;
301 run;
302
303 data vars3(keep=name type length format label pk varnum ctrloptions formatd);
304 set vars(rename=(format=format2 type=type2));
305 name=upcase(name);
306 /* not interested in transaction or processing dates
307 (append table must be supplied without them) */
308 if name not in ("&VAR_TXFROM","&VAR_TXTO","&VAR_PROCESSED");
309 if type2=2 or type2=6 then do;
310 length format $49.;
311 if format2='' then format=cats('$',length,'.');
312 else format=cats(format2,formatl,'.');
313 type='char';
314 end;
315 else do;
316 if format2='' then format=cats(length,'.');
317 else if upcase(format2)='DATETIME' and formatl=0 then format='DATETIME.';
318 else format=cats(format2,formatl,'.',formatd);
319 type='num';
320 end;
321
322 if name in ('',%upcase(%mf_getQuotedStr(&pk,dlm=%str(,),quote=S)))
323 then PK='YES';
324
325 length ctrlOptions $500;
326 if name="_____DELETE__THIS__RECORD_____" then ctrlOptions='["No","Yes"]';
327 else ctrlOptions='';
328 run;
329 %mp_abort(iftrue= (&syscc ne 0)
330 ,mac=&_program..sas
331 ,msg=%str(syscc=&syscc at 242 (vars3 step) in &_program \n
332 %superq(syserrortext)
333 )
334 )
335
336 %global jsdttmvars jsdtvars jstmvars;
337 data vars4;
338 set vars3;
339 length coltype $500.;
340 format=upcase(format);
341 coltype=cats('{"data":"',name,'"');
342 if ctrlOptions ne '' then
343 colType=cats(coltype,',"type":"dropdown","source":',ctrlOptions,"}");
344 else if type='num' then do;
345 if format=:'DATETIME' or format=:'E8601DT' or format=:'NLDATM'
346 then do;
347 colType=cats(coltype,',"type":"datetime"}');
348 /* build var list to reformat datetimes in javascript format */
349 call symput('jsdttmvars',symget('jsdttmvars')!!' '!!name);
350 end;
351 else if format=:'DATE' or format=:'DDMMYY' or format=:'MMDDYY'
352 or format=:'YYMMDD' or format=:'E8601DA' or format=:'B8601DA'
353 or format=:'MONYY' or format=:'NLDATE'
354 then do;
355 /* see bottom of file for more date formats!! */
356 /* also when updating, update stagedata.sas and mp_getcols.sas
357 and mpe_loader.sas */
358 colType=cats(coltype,',"type":"date"}');
359 /* build var list to reformat as javascript dates */
360 call symput('jsdtvars',symget('jsdtvars')!!' '!!name);
361 end;
362 else if format=:'TIME' or format=:'HHMM' then do;
363 colType=cats(coltype,',"type":"time"}');
364 /* build var list to reformat as javascript times */
365 call symput('jstmvars',symget('jstmvars')!!' '!!name);
366 end;
367 else do;
368 /* is standard numeric but need to ascertain precision */
369 retain base '000000000000000000';
370 if formatd>0 then numFormat=cats('.',substr(base,1,formatd));
371 colType=cats(coltype,',"type":"numeric","format":"0',numFormat,'"}');
372 end;
373 end;
374 else colType=cats(coltype,'}');
375 output;
376 putlog (_all_)(=);
377 run;
378
379 %mp_abort(iftrue= (&syscc ne 0)
380 ,mac=&_program..sas
381 ,msg=%str(syscc=&syscc at 283 (null step) in &_program)
382 )
383
384 PROC FORMAT;
385 picture yymmddThhmmss (default=28) other='%0Y-%0m-%0d %0H:%0M:%0s'
386 (datatype=datetime);
387 picture JSyymmdd other='%0Y-%0m-%0d' (datatype=date);
388 picture JShhmmss (default=16) other='%0H:%0M:%0s' (datatype=time);
389 RUN;
390 /* before we send the data, need to rebuild all date & datetime vars as char*/
391 %let finalvars=%mf_getvarlist(work.outdata);
392 data sasdata;
393 /* set formats & col order ahead of rename+import */
394 informat &finalvars ;
395 /* read dataset and rename date / datetime vars as necessary */
396 set outdata
397 %if %length(&jsdttmvars&jsdtvars&jstmvars)>0 %then %do;
398 (rename=(
399 %local dtvarnum dtvar tmvar;
400 /* temp datetime vars end in _____ */
401 %do dtvarnum=1 %to %sysfunc(countw(&jsdttmvars,%str( )));
402 %let dtvar=%scan(&jsdttmvars ,&dtvarnum);
403 &dtvar=_____&dtvarnum._____
404 %end;
405 /* temp date vars do not end in _____ */
406 %do dtvarnum=1 %to %sysfunc(countw(&jsdtvars,%str( )));
407 %let dtvar=%scan( &jsdtvars,&dtvarnum);
408 &dtvar=_____&dtvarnum
409 %end;
410 /* temp time vars end in ___tm */
411 %do tmvarnum=1 %to %sysfunc(countw(&jstmvars,%str( )));
412 %let tmvar=%scan( &jstmvars,&tmvarnum);
413 &tmvar=_____&tmvarnum.___tm
414 %end;
415 ))
416 %end;
417 ;
418 %if %length(&jsdttmvars)>0 %then %do ;
419 %do dtvarnum=1 %to %sysfunc(countw(&jsdttmvars,%str( )));
420 %let dtvar=%scan(&jsdttmvars,&dtvarnum);
421 &dtvar=cats(put(_____&dtvarnum._____,yymmddThhmmss28.));
422 if &dtvar="ERROR" then call missing(&dtvar);
423 drop _____&dtvarnum._____;
424 %end;
425 %end;
426 %if %length(&jsdtvars)>0 %then %do;
427 %do dtvarnum=1 %to %sysfunc(countw(&jsdtvars,%str( )));
428 %let dtvar=%scan(&jsdtvars,&dtvarnum);
429 &dtvar=cats(put(_____&dtvarnum,JSyymmdd.));
430 if &dtvar="ERROR" then call missing(&dtvar);
431 drop _____&dtvarnum;
432 %end;
433 %end;
434 %if %length(&jstmvars)>0 %then %do;
435 %do tmvarnum=1 %to %sysfunc(countw(&jstmvars,%str( )));
436 %let tmvar=%scan(&jstmvars,&tmvarnum);
437 &tmvar=cats(put(_____&tmvarnum.___tm,JShhmmss14.));
438 if &tmvar="ERROR" then call missing(&tmvar);
439 drop _____&tmvarnum.___tm;
440 %end;
441 %end;
442 output;
443 run;
444
445 /* get the relevant approvers for the drop down */
446 %put getting approvers;
447 %local sas_groups sas_i sas_group;
448 proc sql noprint;
449 select distinct sas_Group into: sas_groups separated by "|"
450 from &mpelib..mpe_security
451 where libref="%scan(&orig_libds,1,.)"
452 and dsn="%scan(&orig_libds,2,.)"
453 and access_level='APPROVE'
454 and &dc_dttmtfmt. lt TX_TO;
455
456 %if %length(&sas_groups)=0 %then %do;
457 %dc_getgroupmembers(&dc_admin_group,outds=work.access1)
458 %end;
459 %else %do sas_i=1 %to %sysfunc(countw(&sas_groups,%str(|)));
460 %let sas_group=%scan(&sas_Groups,&sas_i,%str(|));
461 %dc_getgroupmembers(&sas_group,outds=work.temp&sas_i)
462 proc append base=work.access1 data=work.temp&sas_i;run;
463 %end;
464
465%mend mpestp_getdata;
466
467%mpestp_getdata()
468
469/* mp_abort cannot exit cleanly from inside a %include, so an abort there
470 (eg in a hook script run via mp_include) only records the error in
471 work.mp_abort_errds. mode=INCLUDE picks that up and aborts properly here. */
472%mp_abort(mode=INCLUDE)
473
474/* extract column level security rules */
475%mpe_columnlevelsecurity(%scan(&libds,1,.),%scan(&libds,2,.),work.sasdata
476 ,mode=EDIT
477 ,clsds=&mpelib..mpe_column_level_security
478 ,groupds=work.groups /* was created in mpe_filtermaster */
479 ,outds=work.sasdata1
480 ,outmeta=work.cls_rules
481)
482
483/* get labels - pull column names from the CLS-filtered WORK dataset but
484 join to mpe_datadictionary using the underlying LIB.DSN reference */
485%mpe_getlabels(COLUMNS,sasdata1,tgt_ds=&libds,outds=spec)
486%mp_abort(iftrue= (&syscc ne 0)
487 ,mac=&_program
488 ,msg=%str(syscc=&syscc extracting spec info)
489)
490
491/* extract col info */
492%mp_getcols(&libds, outds=cols1)
493
494/* join with cls rules. Trim COLS payload in the SQL below - DDTYPE
495 C=CHARACTER N=NUMERIC (dates kept in full), VARNUM dropped (client
496 relies on column order, not position) */
497proc sql;
498create table work.cols as
499 select a.NAME
500 ,coalesce(c.desc,a.NAME) as LABEL
501 ,a.FMTNAME
502 ,case a.DDTYPE
503 when 'CHARACTER' then 'C'
504 when 'NUMERIC' then 'N'
505 else a.DDTYPE end as DDTYPE
506 ,case b.cls_hide
507 when 1 then 'HIDE'
508 when 0 then 'EDIT'
509 else 'READ' end as CLS_RULE
510 ,c.memlabel
511 ,c.longdesc
512 ,d.colType
513 from work.cols1(drop=varnum) a
514 left join work.cls_rules b
515 on a.NAME=b.CLS_VARIABLE_NM
516 left join work.spec c
517 on a.NAME=c.NAME
518 left join work.vars4 d
519 on a.NAME=d.NAME;
520
521proc sql;
522create table approvers as select distinct membername as personname
523 ,membername as email, membername as userid
524 from work.access1;
525/*
526create table access3 as select b.userid,b.email
527 from access2 a
528 ,support.users b
529 where a.personname=b.userid
530 and a.personname ne "%mf_getuser()"
531 and %sysfunc(datetime()) lt b.tx_to_dttm
532 order by 1;
533*/
534data _null_;
535 infile filtref end=eof;
536 input;
537 length filter_text $32767;
538 retain filter_text;
539 filter_text=catx(' ',filter_text,_infile_);
540 if eof then do;
541 if cats(filter_text)='1=1' then filter_text='';
542 call symputx('filter_text',filter_text);
543 end;
544run;
545
546%put params;
547%let ismap=0;
548proc sql noprint;
549select count(*) into: ismap from &mpelib..mpe_xlmap_info
550 where XLMAP_TARGETLIBDS="&orig_libds" and &dc_dttmtfmt. le TX_TO;
551
552data sasparams;
553 length colHeaders $20000 filter_text $32767;
554 colHeaders=cats(upcase("%mf_getvarlist(sasdata1,dlm=%str(,))"));
555 pkCnt=countw("&pk");
556 pk="&pk";
557 dtvars=compbl("&jsdtvars");
558 dttmvars=compbl("&jsdttmvars");
559 tmvars=compbl("&jstmvars");
560 loadtype=symget('loadtype');
561 if trim(symget('rk_underlying')) ne '' then rk_flag=1;
562 else rk_flag=0;
563 filter_text=symget('filter_text');
564 if %mf_nobs(work.cls_rules)=0 then cls_flag=0;
565 else cls_flag=1;
566 put (_all_)(=);
567 if "&orig_libds"="&mpelib..MPE_XLMAP_DATA" or &ismap ne 0 then ismap=1;
568 else ismap=0;
569run;
570
571
572/* Extract validation DQ Rules */
573proc sort data=&mpelib..mpe_validations
574 (where=(&dc_dttmtfmt. le TX_TO
575 and BASE_LIB="%scan(&orig_libds,1,.)" and BASE_DS="%scan(&orig_libds,2,.)"
576 and rule_active=1))
577 out=dqrules (keep=base_col rule_type rule_value);
578 by base_col rule_type rule_value;
579run;
580
581/* merge with NOTNULL constraints in the physical table */
582proc sql;
583create table _data_ as
584 select * from dqrules
585union
586 select upcase(name) as base_col
587 ,'NOTNULL' as rule_type
588 ,'' as rule_value
589 from dictionary.columns
590 where upcase(libname)="%scan(&orig_libds,1,.)"
591 and upcase(memname)="%scan(&orig_libds,2,.)"
592 and upcase(name) in (select name from vars3)
593 and notnull='yes'
594 order by 1,2,3;
595data dqrules;
596 set &syslast;
597 by base_col rule_type rule_value;
598 if last.rule_type;
599 if rule_type in ('HARDSELECT','SOFTSELECT') and countw(rule_value)=3 then
600 do;
601 retain x 0; x+1;
602 call symputx(cats('source',x),rule_value);
603 %let sourcecnt=0;
604 call symputx('sourcecnt',x);
605 call symputx(cats('base_col',x),base_col);
606 end;
607run;
608
609proc sql;
610create table dqdata as
611 select distinct base_column as base_col length=32
612 ,upcase(base_column) as rule_value length=74 /* deprecated */
613 ,selectbox_value as rule_data length=1000
614 ,selectbox_order
615 from &mpelib..mpe_selectbox
616 where &dc_dttmtfmt. lt ver_to_dttm
617 and select_lib="%scan(&orig_libds,1,.)"
618 and select_ds="%scan(&orig_libds,2,.)";
619
620%mp_abort(iftrue= (&syscc ne 0)
621 ,mac=&_program
622 ,msg=%str(syscc=&syscc during DQ rule validation)
623)
624
625/* extract selectbox data */
626%macro dq_selects();
627 %local x source lib ds col;
628 %do x=1 %to &sourcecnt;
629 %let source=&&source&x;
630 %let lib=%scan(&source,1,.);
631 %let ds=%scan(&source,2,.);
632 %let col=%scan(&source,3,.);
633 %put &=source;
634 %put &=lib;
635 %dc_assignlib(READ,&lib)
636 %dc_casload(&lib..&ds)
637 proc sql;
638 create table dqdata&x as
639 select distinct "&&base_col&x" as base_col length=32
640 ,"&source" as rule_value length=74
641 ,cats(&col) as rule_data length=1000
642 ,&col as tmp_order
643 from &lib..&ds
644 order by tmp_order;
645 /* ensure both numerics and char vals are ordered correctly */
646 data work.dqdata&x (drop=tmp_order);
647 set work.dqdata&x;
648 selectbox_order=_n_;
649 run;
650 %mp_abort(iftrue= (&syscc ne 0)
651 ,mac=&_program
652 ,msg=%str(syscc=&syscc when selecting &&base_col&x from &orig_libds)
653 )
654 proc append base=dqdata data=dqdata&x;run;
655 proc sql; drop table dqdata&x;
656 %end;
657%mend dq_selects;
658%dq_selects()
659
660proc sort data=dqdata;
661 /* order by selectbox_order then the value */
662 by base_col selectbox_order rule_data;
663run;
664
665%mp_getmaxvarlengths(work.sasdata1,outds=maxvarlengths)
666
667data maxvarlengths;
668 set maxvarlengths;
669 if name='_____DELETE__THIS__RECORD_____' then mAXLEN=3;
670run;
671
672data xl_rules;
673 set &mpelib..mpe_excel_config;
674 where &dc_dttmtfmt. lt tx_to;
675 where also upcase(xl_libref)="%scan(&orig_libds,1,.)";
676 where also upcase(xl_table)="%scan(&orig_libds,2,.)";
677 where also xl_active=1;
678 keep xl_column xl_rule;
679run;
680
681%mpe_dsmeta(&orig_libds, outds=dsmeta)
682
683%mpe_getversions(&mpelib,
684 %scan(&orig_libds,1,.),
685 %scan(&orig_libds,2,.),
686 outds=versions
687)
688
689
690/* send to the client */
691%webout(OPEN)
692%webout(OBJ,approvers)
693%webout(OBJ,cols)
694%webout(OBJ,dqdata,missing=STRING)
695%webout(OBJ,dqrules)
696%webout(OBJ,dsmeta)
697%webout(OBJ,maxvarlengths)
698%webout(OBJ,query)
699%webout(OBJ,sasdata1,fmt=N,missing=STRING,showmeta=YES,dslabel=sasdata)
700%webout(OBJ,sasparams)
701%webout(OBJ,versions)
702%webout(OBJ,xl_rules)
703%webout(CLOSE)
704
705/*
706$N8601Bw
707$N8601BAw
708$N8601Ew
709$N8601EAw
710$N8601EHw
711$N8601EXw
712$N8601Hw
713$N8601Xw
714B8601DAw
715B8601DNw
716B8601DTw
717B8601DZw
718B8601LZw
719B8601TMw
720B8601TZw
721DATEw
722DATEAMPMw
723DATETIMEw
724DAYw
725DDMMYYw
726DDMMYYxw
727DOWNAMEw
728DTDATEw
729DTMONYYw
730DTWKDATXw
731DTYEARw
732DTYYQCw
733E8601DAw
734E8601DNw
735E8601DTw
736E8601DZw
737E8601LZw
738E8601TMw
739E8601TZw
740HHMMw
741HOURw
742JULDAYw
743JULIANw
744MMDDYYw
745MMDDYYxw
746MMSSw
747MMYYw
748MMYYxw
749MONNAMEw
750MONTHw
751MONYYw
752PDJULGw
753PDJULIw
754QTRw
755QTRRw
756TIMEw
757TIMEAMPMw
758TODw
759WEEKDATEw
760WEEKDATXw
761WEEKDAYw
762WEEKUw
763WEEKVw
764WEEKWw
765WORDDATEw
766WORDDATXw
767YEARw
768YYMMw
769YYMMxw
770YYMMDDw
771YYMMDDxw
772YYMONw
773YYQw
774YYQxw
775YYQRw
776YYQRxw
777$N8601BAw
778$N8601Ew
779$N8601EAw
780$N8601EHw
781$N8601EXw
782$N8601Hw
783$N8601Xw
784B8601DAw
785B8601DNw
786B8601DTw
787B8601DZw
788B8601LZw
789B8601TMw
790B8601TZw
791E8601DAw
792E8601DNw
793E8601DTw
794E8601DZw
795E8601LZw
796E8601TMw
797E8601TZw
798*/
799%mpeterm()