<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Advanced use of PROC FORMAT in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/Advanced-use-of-PROC-FORMAT/m-p/829032#M327516</link>
    <description>&lt;P&gt;Hi,&lt;/P&gt;
&lt;P&gt;it was definitely a good idea to treat the range as a regex and you do not need a fcmp&lt;/P&gt;
&lt;P&gt;Since it's for age, I suspect you would like to produce an error if it's &amp;gt;120 or &amp;gt;A20&lt;/P&gt;
&lt;P&gt;Then this code is for you:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc format;
   invalue isage (default=5) '/^(\d\d?)|(11\d)|(120)$/'   (regexp)  = _same_ other=[A10x.]; *Match ages btw. 0-120;
   invalue A10x(default=5) 's/^A(\d)$/10$1/'              (regexpe) = _same_ other=[A1x.];  *Match A1-9 =&amp;gt; ages btw. 101-109;
   invalue A1x(default=5) 's/^(A([0-1]\d))$/1$2/'         (regexpe) = _same_ other=[A2x.]; *Match A0[0-9],Match A1[0-9] =&amp;gt; ages btw. 100-119;
   invalue A2x(default=5) 's/^(A(20))$/1$2/'              (regexpe) = _same_ other=_error_; *Match A20 =&amp;gt; ages btw. 100-120;
run;


data test; 
   input x:best. y:isage.; 
   put x= y=; 
   datalines; 
0 00
1 100
2 145
3 132
4 102
5 A5
6 A00
7 A19
8 A20
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;y=121 would produce an error, same as y=A21&lt;/P&gt;
&lt;P&gt;&lt;CODE class=" language-sas"&gt;&lt;/CODE&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Wed, 17 Aug 2022 14:14:29 GMT</pubDate>
    <dc:creator>Oligolas</dc:creator>
    <dc:date>2022-08-17T14:14:29Z</dc:date>
    <item>
      <title>Advanced use of PROC FORMAT</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Advanced-use-of-PROC-FORMAT/m-p/828982#M327488</link>
      <description>&lt;P&gt;Hello Everyone,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I want to use an INFORMAT in order to convert an alphanumeric variable that holds the age of a person. However, this turns out to be quite cumbersome. Reason is, that all "ages" greater than 99 years are expressed as "A0", "A1", etc. So for example, the age of one-hundred-and-forty-four (144) would be expressed as "A44".&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;How can I built a valid informat which takes the above circumstances into account? I tried using the tricks outlined here:&lt;/P&gt;
&lt;P&gt;&lt;A href="https://support.sas.com/resources/papers/proceedings12/245-2012.pdf" target="_blank"&gt;https://support.sas.com/resources/papers/proceedings12/245-2012.pdf&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;A href="https://communities.sas.com/t5/SAS-Tips-from-the-Community/SAS-Tip-Reg-Exp-Substitution-in-Proc-Format/m-p/442549#M158" target="_blank"&gt;https://communities.sas.com/t5/SAS-Tips-from-the-Community/SAS-Tip-Reg-Exp-Substitution-in-Proc-Format/m-p/442549#M158&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;
proc fcmp outlib=work.functions.smd;
 function charagetonum(charage) ;
 return( 100 + input(scan(charage,1,"A"),5.));
 endsub;
run;


options cmplib=(work.functions);
 

proc format;
   invalue bla (default=5) other=[charagetonum()];
 

   invalue isnum (default=5) 
    '/[0-9]/'   (regexpe) = _same_ 
    '/A+[0-9]/' (regexpe) = [bla. ]
    other=_error_
    ; 
run;

data _null_; 
   input alter:isnum. @@; 
   put alter= ; 
   datalines; 
00 25 26 A6 89 A9 8163 23 83 34 A3 78 35 62 
25 26 A6 A6 A79 103 99 A0 A1 A3 A2 A9 A10 " " 
;
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;So far, I have not been able to get it going!&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Does anybody have any ideas?&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;As I mentioned above: I want to "solve" it using a informat.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 17 Aug 2022 09:53:37 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Advanced-use-of-PROC-FORMAT/m-p/828982#M327488</guid>
      <dc:creator>FK1</dc:creator>
      <dc:date>2022-08-17T09:53:37Z</dc:date>
    </item>
    <item>
      <title>Re: Advanced use of PROC FORMAT</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Advanced-use-of-PROC-FORMAT/m-p/828999#M327494</link>
      <description>&lt;P&gt;Hello&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/114220"&gt;@FK1&lt;/a&gt;,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Here's a numeric informat which leaves numeric values unchanged (by reading them with the 32. informat) and which reads A0, ..., A99 as 100, ..., 199. If needed, A00, ..., A09 (as alternative notations for 100, ..., 109) could be added to the definition.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data ageinf;
retain fmtname 'ageinf' type 'I';
length start $3;
do _n_=0 to 99;
  start=cat('A',_n_);
  label=put(100+_n_,3.);
  output;
end;
hlo='OF';
label='32.';
output;
run;

proc format cntlin=ageinf;
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Edit: If you want to see the START and END values sorted numerically in &lt;A href="https://documentation.sas.com/doc/en/pgmsascdc/9.4_3.5/proc/n1c16dxnndwfzyn14o1kb8a4312m.htm#n1ao4kkkhyjzbjn1swdcwm1qhkx4" target="_blank" rel="noopener"&gt;FMTLIB&lt;/A&gt; output, add&lt;/P&gt;
&lt;PRE&gt;hlo 'S '&lt;/PRE&gt;
&lt;P&gt;(note the trailing blank) to the RETAIN statement.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Edit 2: Another useful addition to the HLO variable might be 'J' so that A&lt;EM&gt;xx&lt;/EM&gt; values with leading blanks would be interpreted as if they were left-justified.&lt;/P&gt;
&lt;PRE&gt;hlo 'S&lt;STRONG&gt;J&lt;/STRONG&gt;'&lt;/PRE&gt;</description>
      <pubDate>Wed, 17 Aug 2022 12:38:46 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Advanced-use-of-PROC-FORMAT/m-p/828999#M327494</guid>
      <dc:creator>FreelanceReinh</dc:creator>
      <dc:date>2022-08-17T12:38:46Z</dc:date>
    </item>
    <item>
      <title>Re: Advanced use of PROC FORMAT</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Advanced-use-of-PROC-FORMAT/m-p/829000#M327495</link>
      <description>&lt;P&gt;I'm not near a SAS machine, so I can not provide a testet code answer. But, unless this is more of a Proc Format Regex training thing, I think the logic of testing whether an input value has 'A' in it is much easier to create directly in the Proc FCMP.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;This would make your Proc Format Statement simpler and the code easier to test and debug &lt;span class="lia-unicode-emoji" title=":slightly_smiling_face:"&gt;🙂&lt;/span&gt;&lt;/P&gt;</description>
      <pubDate>Wed, 17 Aug 2022 11:56:29 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Advanced-use-of-PROC-FORMAT/m-p/829000#M327495</guid>
      <dc:creator>PeterClemmensen</dc:creator>
      <dc:date>2022-08-17T11:56:29Z</dc:date>
    </item>
    <item>
      <title>Re: Advanced use of PROC FORMAT</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Advanced-use-of-PROC-FORMAT/m-p/829032#M327516</link>
      <description>&lt;P&gt;Hi,&lt;/P&gt;
&lt;P&gt;it was definitely a good idea to treat the range as a regex and you do not need a fcmp&lt;/P&gt;
&lt;P&gt;Since it's for age, I suspect you would like to produce an error if it's &amp;gt;120 or &amp;gt;A20&lt;/P&gt;
&lt;P&gt;Then this code is for you:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc format;
   invalue isage (default=5) '/^(\d\d?)|(11\d)|(120)$/'   (regexp)  = _same_ other=[A10x.]; *Match ages btw. 0-120;
   invalue A10x(default=5) 's/^A(\d)$/10$1/'              (regexpe) = _same_ other=[A1x.];  *Match A1-9 =&amp;gt; ages btw. 101-109;
   invalue A1x(default=5) 's/^(A([0-1]\d))$/1$2/'         (regexpe) = _same_ other=[A2x.]; *Match A0[0-9],Match A1[0-9] =&amp;gt; ages btw. 100-119;
   invalue A2x(default=5) 's/^(A(20))$/1$2/'              (regexpe) = _same_ other=_error_; *Match A20 =&amp;gt; ages btw. 100-120;
run;


data test; 
   input x:best. y:isage.; 
   put x= y=; 
   datalines; 
0 00
1 100
2 145
3 132
4 102
5 A5
6 A00
7 A19
8 A20
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;y=121 would produce an error, same as y=A21&lt;/P&gt;
&lt;P&gt;&lt;CODE class=" language-sas"&gt;&lt;/CODE&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 17 Aug 2022 14:14:29 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Advanced-use-of-PROC-FORMAT/m-p/829032#M327516</guid>
      <dc:creator>Oligolas</dc:creator>
      <dc:date>2022-08-17T14:14:29Z</dc:date>
    </item>
    <item>
      <title>Re: Advanced use of PROC FORMAT</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Advanced-use-of-PROC-FORMAT/m-p/829064#M327528</link>
      <description>&lt;P&gt;You seem to be working way too hard.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc fcmp outlib=work.functions.smd;
 function charagetonum(charage $) ;
   if charage=:'A' then value=100+input(substr(charage,2),32.);
   else value=input(charage,32.);
   return(value);
 endsub;
run;

options cmplib=(work.functions);

proc format;
   invalue charagetonum(default=5) other=[charagetonum()];
run;

data test;
   input age :charagetonum. @@; 
datalines; 
00 25 26 A6 89 A9 8163 23 83 34 A3 78 35 62 
25 26 A6 A6 A79 103 99 A0 A1 A3 A2 A9 A10 .
;

proc print;
run;&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Wed, 17 Aug 2022 16:34:54 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Advanced-use-of-PROC-FORMAT/m-p/829064#M327528</guid>
      <dc:creator>Tom</dc:creator>
      <dc:date>2022-08-17T16:34:54Z</dc:date>
    </item>
    <item>
      <title>Re: Advanced use of PROC FORMAT</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Advanced-use-of-PROC-FORMAT/m-p/829334#M327665</link>
      <description>&lt;P&gt;Thank you&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/159"&gt;@Tom&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/77163"&gt;@Oligolas&lt;/a&gt;&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/31304"&gt;@PeterClemmensen&lt;/a&gt;&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/32733"&gt;@FreelanceReinh&lt;/a&gt;&amp;nbsp;for your valuable comments!&lt;/P&gt;</description>
      <pubDate>Fri, 19 Aug 2022 11:18:34 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Advanced-use-of-PROC-FORMAT/m-p/829334#M327665</guid>
      <dc:creator>FK1</dc:creator>
      <dc:date>2022-08-19T11:18:34Z</dc:date>
    </item>
  </channel>
</rss>

