<?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: The concat function to rule them all in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/The-concat-function-to-rule-them-all/m-p/770450#M244438</link>
    <description>&lt;P&gt;Of course, FCMP's limitations mean this function cannot be as convenient as a SAS Institute-issued function. The main restrictions are: Strings only as inputs*, all strings must have the same length, and having to build an array before using the function.&amp;nbsp;A missing feature would be option v to enable/disable using the format associated with each variable, instead of supplying a global format to all variables. This too could only be done by a native function.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;In the meantime this serves its purpose for me. &lt;span class="lia-unicode-emoji" title=":slightly_smiling_face:"&gt;🙂&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;* One can easily write a very similar function for numbers only, but the limitations remain. I'll write it nonetheless since the default &lt;FONT face="courier new,courier"&gt;best.&lt;/FONT&gt; format of the CAT functions is not always suitable.&lt;/P&gt;</description>
    <pubDate>Sun, 26 Sep 2021 21:48:48 GMT</pubDate>
    <dc:creator>ChrisNZ</dc:creator>
    <dc:date>2021-09-26T21:48:48Z</dc:date>
    <item>
      <title>The concat function to rule them all</title>
      <link>https://communities.sas.com/t5/SAS-Programming/The-concat-function-to-rule-them-all/m-p/770172#M244312</link>
      <description>&lt;P&gt;I finally bit the bullet and wrote the concatenation function that I needed.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;this is the first draft, there must be much room for improvement.&lt;/P&gt;
&lt;P&gt;This function can use delimiters, formats, allows missing values to be incorporated, allows quoting, and includes basic cleaning options such as upcase, lowcase, compbl, removing non-printable characters.&lt;/P&gt;
&lt;P&gt;Use as you see fit.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc fcmp outlib=WORK.MYFUNCS.STR;
  function concat(
        DLM     $ /* Delimiter string to insert between concatenated strings                 */
                  /*   The delimiter string is only used if option D is found                */
      , QUOTE   $ /* Character(s) used to surround concatenated strings                      */
                  /*   Single and double quotes can be used                                  */
                  /*   Brackets ( [ { &amp;lt; &amp;gt; } ] )can be used. In this case:                    */
                  /*     Opening brackets ( [ { &amp;lt; are inserted at the start                  */
                  /*     Closing brackets &amp;gt; } ] ) are inserted at the end                    */
                  /*   Multiple characters can be used, except for single and double quotes  */
                  /*   The quoting string is only used if option Q is found                  */
      , FORMAT  $ /* Name of the character format to apply                                   */
                  /*   The format is only used if option F is found                          */
      , OPTIONS $ /* Options driving concatenation. These letters are recognised:            */
                  /*   Q Use quoting characters(s) if provided                               */
                  /*   F Use format if provided                                              */
                  /*   D Use delimiter in concatenated string                                */
                  /*   M Include missing string in concatenated string                       */
                  /*   T Trim string before adding to concatenated string                    */
                  /*   S Strip string before adding to concatenated string                   */
                  /*   C Compbl string before adding to concatenated string                  */
                  /*   U Upcase string before adding to concatenated string                  */
                  /*   L Lowcase string before adding to concatenated string                 */
                  /*   P Propcase string before adding to concatenated string                */
                  /*   N Clean non-printable characters before adding to concatenated string */
      , A[*]    $ /* Character array containing the strings to concatenate                   */
      )
      $ 32767;
    length RESULT S $32767 Q1 Q2 OPT FMT $32 L LF 8;
    RESULT = 'a';                         
    OPT    = upcase(OPTIONS);                                         
    %* Remove request to format if no format is supplied, and set dummy format so ifc() is happy ;
    if ^index(OPT,'F') | (index(OPT,'F') &amp;amp; FORMAT=' ') then do; OPT=compress(OPT,'F'); FMT='$1.'; end; else FMT=FORMAT;
    %* Set surrounding (quoting) characters ;                                              
    if index(OPT,'Q') &amp;amp; lengthn(QUOTE ) then do;
      if      QUOTE in:('(',')') then do; Q1=repeat('(',length(QUOTE)-1); Q2=repeat(')',length(QUOTE)-1); end;
      else if QUOTE in:('{','}') then do; Q1=repeat('{',length(QUOTE)-1); Q2=repeat('}',length(QUOTE)-1); end;
      else if QUOTE in:('[',']') then do; Q1=repeat('[',length(QUOTE)-1); Q2=repeat(']',length(QUOTE)-1); end;
      else if QUOTE in:('&amp;lt;','&amp;gt;') then do; Q1=repeat('&amp;lt;',length(QUOTE)-1); Q2=repeat('&amp;gt;',length(QUOTE)-1); end;
      else if index(QUOTE,'"')   then do; Q1='"'   ; Q2='"'   ; end; 
      else if index(QUOTE,"'")   then do; Q1="'"   ; Q2="'"   ; end; 
      else do;                            Q1=QUOTE ; Q2=QUOTE ; end;  
    end;                                                                

    %* Get variable length. Does not go under 8;
    S=A[1]||'a'; L=length(S)-1; 
    %* Loop through the values and append;
    do I = 1 to dim(A);
      S=ifc(index(OPT,'C'), compbl  (trim(A[I])  ), trim(A[I]));
      S=ifc(index(OPT,'U'), upcase  (trim(S   )  ), trim(S   ));
      S=ifc(index(OPT,'L'), lowcase (trim(S   )  ), trim(S   ));
      S=ifc(index(OPT,'P'), propcase(trim(S   )  ), trim(S   ));
      if index(OPT,'F') then do; S=putc(substrn(S,1,L),FMT) ; LF=length(S); end;
   
      if lengthn(S) | index(OPT,'M') then
      RESULT = ifc(index(OPT,'T'), trim(substrn(RESULT,1,length(RESULT)-1)), substrn(RESULT,1,length(RESULT)-1)) %* Add previous RESULT: Trim it if needed, otherwise use the length saved ;
             || ifc( I=1 | ^index(OPT,'D'), '', ifc(lengthn(DLM), DLM, ' '))                                     %* Add delimiter if needed                                                ;
             || ifc(QUOTE in:('"',"'")                                                                           %* Add quote character(s)                                                 ;
               , quote( ifc(index(OPT,'S'), strip(S)                                                             %* If double or single quote, use quote function                          ;
                      , ifc(index(OPT,'T'), trim(S ), substrn(S,1,max(L,LF)) ))                                  %*    Strip or trim if needed                                             ; 
                 , QUOTE)
               , trimn(Q1)                                                                                       %* If not double or single quote, concatenate manually                    ;
               || ifc(index(OPT,'S'), strip(S)                                                                   %*    Strip or trim if needed                                             ; 
                , ifc(index(OPT,'T'), trim(S ), substrn(S,1,max(L,LF)) ))
               || trimn(Q2) 
               )
             || 'a';                                                                                             %* Add end-of-string marker                                               ; 
    end;
                    
    return (substr(RESULT,1,length(RESULT)-1));                                      
  endsub;

run;

options cmplib = WORK.MYFUNCS  ;  

data TEST;
  A = 'orange         ';
  B = 'strawberry     ';
  C = '               ';
  D = 'pear           ';
  E = 'custard   apple';
  F = '"paul''s" berry ';

  array ARR[*] A B C D E F ;

  length S $ 240;
  S = concat('|'  , '{'  , '$revers20.', 't     ', ARR); output;
  S = concat('|'  , '{'  , '$revers20.', 'd     ', ARR); output;
  S = concat('|'  , '{'  , '$revers20.', 'f     ', ARR); output;
  S = concat('|'  , '{'  , '$revers20.', 'q     ', ARR); output;
  S = concat('|'  , '{'  , '$revers20.', 'm     ', ARR); output;
  S = concat('|'  , '{'  , '$revers20.', 'u     ', ARR); output;
  S = concat('-|-', ']]]', '$hex20.   ', 'tdfqmu', ARR); output;
  S = concat(' | ', '{'  , '$8.       ', 'tdfqmp', ARR); output;
  S = concat(' | ', '"'  , '$8.       ', 'qdtu  ', ARR); output;  
run;

&lt;/CODE&gt;&lt;/PRE&gt;
&lt;DIV class="branch"&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ChrisNZ_0-1632476013092.png" style="width: 884px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/64030iE26CBA082DC47F71/image-dimensions/884x231?v=v2" width="884" height="231" role="button" title="ChrisNZ_0-1632476013092.png" alt="ChrisNZ_0-1632476013092.png" /&gt;&lt;/span&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;/DIV&gt;</description>
      <pubDate>Fri, 24 Sep 2021 09:34:46 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/The-concat-function-to-rule-them-all/m-p/770172#M244312</guid>
      <dc:creator>ChrisNZ</dc:creator>
      <dc:date>2021-09-24T09:34:46Z</dc:date>
    </item>
    <item>
      <title>Re: The concat function to rule them all</title>
      <link>https://communities.sas.com/t5/SAS-Programming/The-concat-function-to-rule-them-all/m-p/770206#M244337</link>
      <description>&lt;P&gt;Hi, you've seen LOTR too often, remember Sauron looses it all in the end.&lt;/P&gt;
&lt;P&gt;Just joking.&lt;/P&gt;
&lt;P&gt;Well thank you for sharing, it's interesting since you're using fcmp&lt;/P&gt;</description>
      <pubDate>Fri, 24 Sep 2021 12:25:46 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/The-concat-function-to-rule-them-all/m-p/770206#M244337</guid>
      <dc:creator>Oligolas</dc:creator>
      <dc:date>2021-09-24T12:25:46Z</dc:date>
    </item>
    <item>
      <title>Re: The concat function to rule them all</title>
      <link>https://communities.sas.com/t5/SAS-Programming/The-concat-function-to-rule-them-all/m-p/770214#M244341</link>
      <description>&lt;P&gt;Consider making this an article in the library, and later maybe a paper for SASGF.&lt;/P&gt;</description>
      <pubDate>Fri, 24 Sep 2021 12:59:11 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/The-concat-function-to-rule-them-all/m-p/770214#M244341</guid>
      <dc:creator>Kurt_Bremser</dc:creator>
      <dc:date>2021-09-24T12:59:11Z</dc:date>
    </item>
    <item>
      <title>Re: The concat function to rule them all</title>
      <link>https://communities.sas.com/t5/SAS-Programming/The-concat-function-to-rule-them-all/m-p/770247#M244355</link>
      <description>&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/77163"&gt;@Oligolas&lt;/a&gt;&amp;nbsp;wrote:&lt;BR /&gt;
&lt;P&gt;Hi, you've seen LOTR too often,&lt;/P&gt;
&lt;HR /&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;And that's a bad thing??? &lt;span class="lia-unicode-emoji" title=":astonished_face:"&gt;😲&lt;/span&gt; Perhaps just read too often. I know I read the books at least 25 times before the movies came out (annual summer activity for awhile).&lt;/P&gt;</description>
      <pubDate>Fri, 24 Sep 2021 14:16:11 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/The-concat-function-to-rule-them-all/m-p/770247#M244355</guid>
      <dc:creator>ballardw</dc:creator>
      <dc:date>2021-09-24T14:16:11Z</dc:date>
    </item>
    <item>
      <title>Re: The concat function to rule them all</title>
      <link>https://communities.sas.com/t5/SAS-Programming/The-concat-function-to-rule-them-all/m-p/770449#M244437</link>
      <description>&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/11562"&gt;@Kurt_Bremser&lt;/a&gt;&amp;nbsp;&amp;nbsp;The last SASGF I attended was San Francisco.&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/15043"&gt;@ScottBass&lt;/a&gt;&amp;nbsp;offered me to speak a few times since, but I always declined. Maybe I'll do that next time. Thank you for your encouragement. &lt;span class="lia-unicode-emoji" title=":slightly_smiling_face:"&gt;🙂&lt;/span&gt;&lt;/P&gt;</description>
      <pubDate>Sun, 26 Sep 2021 02:32:47 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/The-concat-function-to-rule-them-all/m-p/770449#M244437</guid>
      <dc:creator>ChrisNZ</dc:creator>
      <dc:date>2021-09-26T02:32:47Z</dc:date>
    </item>
    <item>
      <title>Re: The concat function to rule them all</title>
      <link>https://communities.sas.com/t5/SAS-Programming/The-concat-function-to-rule-them-all/m-p/770450#M244438</link>
      <description>&lt;P&gt;Of course, FCMP's limitations mean this function cannot be as convenient as a SAS Institute-issued function. The main restrictions are: Strings only as inputs*, all strings must have the same length, and having to build an array before using the function.&amp;nbsp;A missing feature would be option v to enable/disable using the format associated with each variable, instead of supplying a global format to all variables. This too could only be done by a native function.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;In the meantime this serves its purpose for me. &lt;span class="lia-unicode-emoji" title=":slightly_smiling_face:"&gt;🙂&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;* One can easily write a very similar function for numbers only, but the limitations remain. I'll write it nonetheless since the default &lt;FONT face="courier new,courier"&gt;best.&lt;/FONT&gt; format of the CAT functions is not always suitable.&lt;/P&gt;</description>
      <pubDate>Sun, 26 Sep 2021 21:48:48 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/The-concat-function-to-rule-them-all/m-p/770450#M244438</guid>
      <dc:creator>ChrisNZ</dc:creator>
      <dc:date>2021-09-26T21:48:48Z</dc:date>
    </item>
    <item>
      <title>Re: The concat function to rule them all</title>
      <link>https://communities.sas.com/t5/SAS-Programming/The-concat-function-to-rule-them-all/m-p/772665#M245361</link>
      <description>&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/11562"&gt;@Kurt_Bremser&lt;/a&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;A href="https://communities.sas.com/t5/SAS-Communities-Library/The-CONCAT-function-to-rule-them-all/ta-p/772664" target="_self"&gt;Done&lt;/A&gt;&lt;/P&gt;</description>
      <pubDate>Thu, 07 Oct 2021 10:11:16 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/The-concat-function-to-rule-them-all/m-p/772665#M245361</guid>
      <dc:creator>ChrisNZ</dc:creator>
      <dc:date>2021-10-07T10:11:16Z</dc:date>
    </item>
  </channel>
</rss>

