%macro annocheck(anno=anno); options nonotes; data _null_; /* get variable lengths and construct initialization */ dsid = open("&anno"); length s a $ 1000 name $ 16; name = 'Anchor'; link getlen; name = 'Border'; link getlen; name = 'Direction'; link getlen; name = 'Display'; link getlen; name = 'DrawSpace'; link getlen; name = 'FillColor'; link getlen; name = 'FillStyleElement'; link getlen; name = 'Image'; link getlen; name = 'ImageScale'; link getlen; name = 'Justify'; link getlen; name = 'Label'; link getlen; name = 'Layer'; link getlen; name = 'LineColor'; link getlen; name = 'LinePattern'; /* no checks, can be char or num */ name = 'LineStyleElement'; link getlen; name = 'Rotate'; link getlen; name = 'Shape'; link getlen; name = 'TextColor'; link getlen; name = 'TextFont'; link getlen; name = 'TextStyle'; link getlen; name = 'TextStyleElement'; link getlen; name = 'TextWeight'; link getlen; name = 'URL'; link getlen; name = 'x1Space'; link getlen; name = 'x2Space'; link getlen; name = 'xAxis'; link getlen; name = 'xC1'; link getlen; name = 'xC2'; link getlen; name = 'y1Space'; link getlen; name = 'y2Space'; link getlen; name = 'yAxis'; link getlen; name = 'yC1'; link getlen; name = 'yC2'; link getlen; call symputx('len', s); /* used to set lengths */ call symputx('assign', a); /* used to initialize variables */ rc = close(dsid); return; getlen: num = varnum(dsid, name); len = 1; if num then len = varlen(dsid, num); s = catx(' ', s, name, '$', len); a = catx(' ', a, name, '= " ";'); return; run; data _null_; retain dsid; length &len; &assign x1 = .; x2 = .; y1 = .; y2 = .; set &anno end=eof; if _n_ = 1 then dsid = open("&anno"); position = varnum(dsid, "Function"); if not position then do; put 'Function variable not present.'; stop; end; select (lowcase(function)); when ('image') do; position = varnum(dsid, "Image"); if not position then put "Image variable not present with Function='Image'."; end; when ('text') do; position = varnum(dsid, "Label"); if not position then put "Label variable not present with Function='Text'."; end; when ('textcont') do; position = varnum(dsid, "Label"); if not position then put "Label variable not present with Function='TextCont'."; end; when ('arrow', 'line') link bothpairs; when ('polygon', 'polyline', 'polycont', 'oval', 'rectangle') link onepair; otherwise; end; if not (lowcase(function) in (' ' 'text' 'textcont' 'arrow' 'line' 'polygon' 'polyline' 'polycont' 'oval' 'rectangle' 'image')) then put 'Invalid: ' function=; if not (lowcase(anchor) in (' ' 'topleft' 'top' 'topright' 'right' 'bottomright' 'bottom' 'bottomleft' 'left' 'center' )) then put 'Invalid: ' anchor=; if not (lowcase(border) in (' ' 'true' 'false')) then put 'Invalid: ' border=; if not (lowcase(direction) in (' ' 'both' 'in' 'out')) then put 'Invalid: ' direction=; if not (lowcase(display) in (' ' 'all' 'fill' 'outline')) then put 'Invalid: ' display=; if not (lowcase(justify) in (' ' 'center' 'left' 'right')) then put 'Invalid: ' justify=; if not (lowcase(layer) in (' ' 'back' 'front')) then put 'Invalid: ' layer=; if not (lowcase(textstyle) in (' ' 'normal' 'italic')) then put 'Invalid: ' textstyle=; if not (lowcase(textweight) in (' ' 'normal' 'bold')) then put 'Invalid: ' textweight=; if not (lowcase(xaxis) in (' ' 'x' 'x2')) then put 'Invalid: ' xaxis=; if not (lowcase(yaxis) in (' ' 'y' 'y2')) then put 'Invalid: ' yaxis=; %let spaces = ' ' 'datapercent' 'datapixel' 'datavalue' 'graphpercent' 'graphpixel' 'layoutpercent' 'layoutpixel' 'wallpercent' 'wallpixel'; if not (lowcase(drawspace) in (&spaces)) then put 'Invalid: ' drawspace=; if not (lowcase(x1space) in (&spaces)) then put 'Invalid: ' x1space=; if not (lowcase(x2space) in (&spaces)) then put 'Invalid: ' x2space=; if not (lowcase(y1space) in (&spaces)) then put 'Invalid: ' y1space=; if not (lowcase(y2space) in (&spaces)) then put 'Invalid: ' y2space=; if eof then rc = close(dsid); return; bothpairs: n1 = varnum(dsid, "x1" ) ne 0; n2 = varnum(dsid, "x2" ) ne 0; n3 = varnum(dsid, "y1" ) ne 0; n4 = varnum(dsid, "y2" ) ne 0; c1 = varnum(dsid, "xc1") ne 0; c2 = varnum(dsid, "xc2") ne 0; c3 = varnum(dsid, "yc1") ne 0; c4 = varnum(dsid, "yc2") ne 0; if ((n1 + c1) ge 1) + ((n2 + c2) ge 1) + ((n3 + c3) ge 1) + ((n4 + c4) ge 1) ne 4 then link rpt2; n1 = n(x1); n2 = n(x2); n3 = n(y1); n4 = n(y2); c1 = xc1 ne ' '; c2 = xc2 ne ' '; c3 = yc1 ne ' '; c4 = yc2 ne ' '; if ((n1 + c1) ge 1) + ((n2 + c2) ge 1) + ((n3 + c3) ge 1) + ((n4 + c4) ge 1) ne 4 then do; link rpt2; put x1= x2= y1= y2= xc1= xc2= yc1= yc2=; end; if n1 + c1 = 0 then put 'Error: x1 and xC1 are both missing.'; if n2 + c2 = 0 then put 'Error: x2 and xC1 are both missing.'; if n3 + c3 = 0 then put 'Error: y1 and yC1 are both missing.'; if n4 + c4 = 0 then put 'Error: y2 and yC1 are both missing.'; if n1 & c1 then put 'Warning: x1 and xC1 are both nonmissing. ' x1= xc1=; if n2 & c2 then put 'Warning: x2 and xC1 are both nonmissing. ' x2= xc2=; if n3 & c3 then put 'Warning: y1 and yC1 are both nonmissing. ' y1= yc1=; if n4 & c4 then put 'Warning: y2 and yC1 are both nonmissing. ' y2= yc2=; return; onepair: n1 = varnum(dsid, "x1") ne 0; n2 = varnum(dsid, "y1") ne 0; c1 = varnum(dsid, "xc1") ne 0; c2 = varnum(dsid, "yc1") ne 0; if ((n1 + c1) ge 1) + ((n2 + c2) ge 1) ne 2 then link rpt1; n1 = n(x1); n2 = n(y1); c1 = xc1 ne ' '; c2 = yc1 ne ' '; if ((n1 + c1) ge 1) + ((n2 + c2) ge 1) ne 2 then do; link rpt1; put x1= y1= xc1= yc1=; end; if n1 + c1 = 0 then put 'Error: x1 and xC1 are both missing.'; if n2 + c2 = 0 then put 'Error: y1 and yC1 are both missing.'; if n1 & c1 then put 'Warning: x1 and xC1 are both nonmissing. ' x1= xc1=; if n2 & c2 then put 'Warning: y1 and yC1 are both nonmissing. ' y1= yc1=; return; rpt2: put / 'At least one of each pair must be present:' / '(x1,xc1), (x2,xc2), (y1,yc1), (y2,yc2)'; put 'Present variables are: ' @; if n1 then put 'x1 ' @; if n2 then put 'x2 ' @; if n3 then put 'y1 ' @; if n4 then put 'y2 ' @; if c1 then put 'xC1 ' @; if c2 then put 'xC2 ' @; if c3 then put 'yC1 ' @; if c4 then put 'yC2 ' @; put; return; rpt1: put / 'At least one of each pair must be present:' / '(x1,xc1), (x2,xc2)'; put 'Present variables are: ' @; if n1 then put 'x1 ' @; if n2 then put 'y1 ' @; if c1 then put 'xC1 ' @; if c2 then put 'yC1 ' @; put; return; run; options notes; %mend;