<?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: SAS Format contents WITHOUT running a proc or datastep (ie pure macro) in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/SAS-Format-contents-WITHOUT-running-a-proc-or-datastep-ie-pure/m-p/964323#M375572</link>
    <description>&lt;P&gt;If you really want to do this, there is a way using the DOSUBL function, it can be called within a macro, it will execute some code, but not produce any text. The resulting SAS data set is then read using functions. See this example below.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc format;
  value $gender
    "F" = "female"
    "M" = "male"
    other = "others"
  ;
run;

%macro test;
  %local output rc dsid;
  %let output = _mydata;
  %let rc = %sysfunc(dosubl(%str(proc format cntlout=&amp;amp;output;run;)));  
  %let dsid = %sysfunc(open(&amp;amp;output));
  %syscall set(dsid);
  %do %while (%sysfunc(fetch(&amp;amp;dsid)) = 0) ;
    %put &amp;amp;fmtname &amp;amp;start &amp;amp;end &amp;amp;label;
  %end;
  %let rc = %sysfunc(close(&amp;amp;dsid));  
%mend;

%put NOTE: call %nrstr(%test) *%test*;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;As you can see the call of the macro does not create any text, but it does show the contents of the SAS data set in the SAS log.&lt;/P&gt;
&lt;P&gt;I am still interested in the use case of this.&lt;/P&gt;</description>
    <pubDate>Tue, 15 Apr 2025 10:15:23 GMT</pubDate>
    <dc:creator>BrunoMueller</dc:creator>
    <dc:date>2025-04-15T10:15:23Z</dc:date>
    <item>
      <title>SAS Format contents WITHOUT running a proc or datastep (ie pure macro)</title>
      <link>https://communities.sas.com/t5/SAS-Programming/SAS-Format-contents-WITHOUT-running-a-proc-or-datastep-ie-pure/m-p/964289#M375562</link>
      <description>&lt;P&gt;Easy to access format contents with proc format cntlout=work.myContents;&amp;nbsp; &amp;nbsp; etc etc&amp;nbsp;&lt;BR /&gt;However I would like to get the contents in a '&lt;STRONG&gt;pure macro'&lt;/STRONG&gt; style,&amp;nbsp; ie So that I can access the 'start' value of a format WITHOUT having to run a proc or datasetp which limits the situations&amp;nbsp; I can run the macro.&amp;nbsp; &amp;nbsp;Does a FCMP with run_macro allow this perhaps?&lt;/P&gt;&lt;P&gt;cheers&amp;nbsp; rob&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 15 Apr 2025 06:33:40 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/SAS-Format-contents-WITHOUT-running-a-proc-or-datastep-ie-pure/m-p/964289#M375562</guid>
      <dc:creator>robAs</dc:creator>
      <dc:date>2025-04-15T06:33:40Z</dc:date>
    </item>
    <item>
      <title>Re: SAS Format contents WITHOUT running a proc or datastep (ie pure macro)</title>
      <link>https://communities.sas.com/t5/SAS-Programming/SAS-Format-contents-WITHOUT-running-a-proc-or-datastep-ie-pure/m-p/964291#M375564</link>
      <description>&lt;P&gt;Illustrate what you want to achieve with a simple format definition and how you plan to use this format within your macro would help to understand the question better and hopefully answer it.&lt;/P&gt;</description>
      <pubDate>Tue, 15 Apr 2025 06:44:16 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/SAS-Format-contents-WITHOUT-running-a-proc-or-datastep-ie-pure/m-p/964291#M375564</guid>
      <dc:creator>BrunoMueller</dc:creator>
      <dc:date>2025-04-15T06:44:16Z</dc:date>
    </item>
    <item>
      <title>Re: SAS Format contents WITHOUT running a proc or datastep (ie pure macro)</title>
      <link>https://communities.sas.com/t5/SAS-Programming/SAS-Format-contents-WITHOUT-running-a-proc-or-datastep-ie-pure/m-p/964316#M375568</link>
      <description>If you can keep a permanent version of your formats in a CNTLOUT table, you can use SAS File I/O functions to query it. Awkward, but it might fit your purpose?</description>
      <pubDate>Tue, 15 Apr 2025 08:37:52 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/SAS-Format-contents-WITHOUT-running-a-proc-or-datastep-ie-pure/m-p/964316#M375568</guid>
      <dc:creator>LinusH</dc:creator>
      <dc:date>2025-04-15T08:37:52Z</dc:date>
    </item>
    <item>
      <title>Re: SAS Format contents WITHOUT running a proc or datastep (ie pure macro)</title>
      <link>https://communities.sas.com/t5/SAS-Programming/SAS-Format-contents-WITHOUT-running-a-proc-or-datastep-ie-pure/m-p/964317#M375569</link>
      <description>&lt;P&gt;The only practical way to retrieve all START values for a given format is PROC FORMAT. To get the values in any other way would involve reading the catalog file where the format is stored as a binary stream and extract the data, which would probably leave you with 10k of macro code.&lt;/P&gt;</description>
      <pubDate>Tue, 15 Apr 2025 08:46:00 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/SAS-Format-contents-WITHOUT-running-a-proc-or-datastep-ie-pure/m-p/964317#M375569</guid>
      <dc:creator>Kurt_Bremser</dc:creator>
      <dc:date>2025-04-15T08:46:00Z</dc:date>
    </item>
    <item>
      <title>Re: SAS Format contents WITHOUT running a proc or datastep (ie pure macro)</title>
      <link>https://communities.sas.com/t5/SAS-Programming/SAS-Format-contents-WITHOUT-running-a-proc-or-datastep-ie-pure/m-p/964323#M375572</link>
      <description>&lt;P&gt;If you really want to do this, there is a way using the DOSUBL function, it can be called within a macro, it will execute some code, but not produce any text. The resulting SAS data set is then read using functions. See this example below.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc format;
  value $gender
    "F" = "female"
    "M" = "male"
    other = "others"
  ;
run;

%macro test;
  %local output rc dsid;
  %let output = _mydata;
  %let rc = %sysfunc(dosubl(%str(proc format cntlout=&amp;amp;output;run;)));  
  %let dsid = %sysfunc(open(&amp;amp;output));
  %syscall set(dsid);
  %do %while (%sysfunc(fetch(&amp;amp;dsid)) = 0) ;
    %put &amp;amp;fmtname &amp;amp;start &amp;amp;end &amp;amp;label;
  %end;
  %let rc = %sysfunc(close(&amp;amp;dsid));  
%mend;

%put NOTE: call %nrstr(%test) *%test*;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;As you can see the call of the macro does not create any text, but it does show the contents of the SAS data set in the SAS log.&lt;/P&gt;
&lt;P&gt;I am still interested in the use case of this.&lt;/P&gt;</description>
      <pubDate>Tue, 15 Apr 2025 10:15:23 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/SAS-Format-contents-WITHOUT-running-a-proc-or-datastep-ie-pure/m-p/964323#M375572</guid>
      <dc:creator>BrunoMueller</dc:creator>
      <dc:date>2025-04-15T10:15:23Z</dc:date>
    </item>
    <item>
      <title>Re: SAS Format contents WITHOUT running a proc or datastep (ie pure macro)</title>
      <link>https://communities.sas.com/t5/SAS-Programming/SAS-Format-contents-WITHOUT-running-a-proc-or-datastep-ie-pure/m-p/964329#M375573</link>
      <description>&lt;P&gt;Agree with Bruno's suggestion to consider using DOSUBL when you want to write a function-style macro with pure macro code, but want to execute DATA steps or PROC steps.&amp;nbsp; For an introduction to the magic of DOSUBL, the best starting point is Rick Langston's original paper:&amp;nbsp;&lt;A href="https://support.sas.com/resources/papers/proceedings13/032-2013.pdf" target="_blank"&gt;https://support.sas.com/resources/papers/proceedings13/032-2013.pdf&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Since you mention FCMP and run_macro, you might also be interested in earlier papers by Secosky&amp;nbsp;&lt;A href="https://support.sas.com/resources/papers/proceedings12/227-2012.pdf" target="_blank"&gt;https://support.sas.com/resources/papers/proceedings12/227-2012.pdf&lt;/A&gt;&amp;nbsp; and Rhoads&amp;nbsp;&lt;A href="https://www.lexjansen.com/nesug/nesug12/bb/bb14.pdf" target="_blank"&gt;https://www.lexjansen.com/nesug/nesug12/bb/bb14.pdf&lt;/A&gt;&lt;/P&gt;</description>
      <pubDate>Tue, 15 Apr 2025 13:22:56 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/SAS-Format-contents-WITHOUT-running-a-proc-or-datastep-ie-pure/m-p/964329#M375573</guid>
      <dc:creator>Quentin</dc:creator>
      <dc:date>2025-04-15T13:22:56Z</dc:date>
    </item>
    <item>
      <title>Re: SAS Format contents WITHOUT running a proc or datastep (ie pure macro)</title>
      <link>https://communities.sas.com/t5/SAS-Programming/SAS-Format-contents-WITHOUT-running-a-proc-or-datastep-ie-pure/m-p/964378#M375589</link>
      <description>&lt;P&gt;Adding context to my original question:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;We Use DBMS as a data source for sas analytical processes .&lt;BR /&gt;We may want to read/query any of 5000+ tables. Many of these DBMS tables contain a high number of columns with a column name &amp;gt;32 characters which is the SAS max column name length.&lt;/P&gt;&lt;P&gt;Here is a sample of column names over 32 chars:&lt;BR /&gt;accommodation_hospital_charge_quarterly&lt;/P&gt;&lt;P&gt;admission_weekly_item_scores_validation_report&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/P&gt;&lt;P&gt;ancillary_downgrade_non_reported_revenue&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/P&gt;&lt;P&gt;channel_agent_type_mapping_desc&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/P&gt;&lt;P&gt;corporate_discount_policy_count&amp;nbsp;&amp;nbsp;&lt;/P&gt;&lt;P&gt;cover_options_special_offers_preference&lt;/P&gt;&lt;P&gt;cover_options_special_offers_preference_email&amp;nbsp;&amp;nbsp;&lt;/P&gt;&lt;P&gt;cover_options_special_offers_preference_phone&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/P&gt;&lt;P&gt;cover_options_special_offers_preference_sms&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;The column names are excessively long because little attempt has been made in the dbms (snowflake) to keep the name short.&lt;/P&gt;&lt;P&gt;We wish to abbreviate these column names to maintain meaningful descriptions using a standardised and consistent set of rules to reduce the amount of variation.&lt;BR /&gt;For example the first of the above column names would abbreviate to&lt;BR /&gt;accom_hosp_chg_qtly&lt;BR /&gt;adm_wkly_item_scores_validtn_rpt&amp;nbsp;&lt;BR /&gt;etc etc&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;One common programming task is in the creation of views in snowflake. The analyst/programmer is currently hardcoding the abbreviated values such as CVR_OPTNS_SPCL_OFFRS_EML&amp;nbsp; (see example in red below)&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=""&gt;EXAMPLE1
proc sql noerrorstop;
  connect using snowflak;
  execute ( 
           create or replace view edp.workspace._v_TabNameDeleteMeNow  as 
           select  
            CUSTOMER_ECN_NO  as CUSTOMER_ECN_NO
           ,COVER_OPTIONS_SPECIAL_OFFERS_PREFERENCE_EMAIL  as&lt;FONT color="#FF0000"&gt;&lt;STRONG&gt; CVR_OPTNS_SPCL_OFFRS_EML&lt;/STRONG&gt;&lt;/FONT&gt;
           ,COVER_OPTIONS_SPECIAL_OFFERS_PREFERENCE_SMS    as CVR_OPTNS_SPCL_OFFRS_SMS 
           ,COVER_OPTIONS_SPECIAL_OFFERS_PREFERENCE_PHONE  as CVR_OPTNS_SPCL_OFFRS_PHN 
           from edp.CUSTDATA.AEP_CUSTOMER_PERSONAL_DETAILS 
  ) by snowflak;
  disconnect from snowflak;
quit;&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;I would like to change the above by automatically deriving the abbreviated column name using a macro %abbreviate such as&amp;nbsp; below.&lt;BR /&gt;Note that this is 'in-line' right in the middle of a proc, therefore I cannot simply run a macro at this point which runs another proc or data step as it would give a syntax error)&amp;nbsp;&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=""&gt;EXAMPLE2
proc sql noerrorstop;
  connect using snowflak;
  execute ( 
           create or replace view edp.workspace._v_TabNameDeleteMeNow  as 
           select  
            CUSTOMER_ECN_NO  as CUSTOMER_ECN_NO
           ,COVER_OPTIONS_SPECIAL_OFFERS_PREFERENCE_EMAIL  as &lt;FONT color="#FF0000"&gt;&lt;STRONG&gt;%abbreviate&lt;/STRONG&gt;(COVER_OPTIONS_SPECIAL_OFFERS_PREFERENCE_EMAIL )&lt;/FONT&gt;
           ,COVER_OPTIONS_SPECIAL_OFFERS_PREFERENCE_SMS    as %abbreviate(COVER_OPTIONS_SPECIAL_OFFERS_PREFERENCE_SMS)
           ,COVER_OPTIONS_SPECIAL_OFFERS_PREFERENCE_PHONE  as %abbreviate(COVER_OPTIONS_SPECIAL_OFFERS_PREFERENCE_PHONE )  
           from edp.CUSTDATA.AEP_CUSTOMER_PERSONAL_DETAILS 
  ) by snowflak;
  disconnect from snowflak;
quit;&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;I already have a SAS format in the format search path which contains hundreds of ‘accepted’ abbreviations of commonly used words used in the business which looks like this:&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=""&gt;proc format library=xxxx.formats;
  value $abbreviations 
        'Accident'     =’Accdnt'
        'Accommodation'='Accm'
        'Additional'   ='Addnl'
        'Admitted’ = 'Admtd'
        'Admission'	= 'Adm'
        'Agenda'	= 'Agnda'
        'Agent'	='Agnt'
        'Ambulance'	='Amb'
        'Amount'	='Amt'
        'Ancillary'	='Anc'  
    Etc etc etc &lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;So my thought is to write a macro called %abbreviate :&lt;BR /&gt;%abbreviate(Longstring,FormatName);&lt;/P&gt;&lt;OL&gt;&lt;LI&gt;Queries the format to get all the ‘start’ values of the format&amp;nbsp; which is the ‘long string’&lt;/LI&gt;&lt;LI&gt;Create a macro var indexed array &amp;nbsp;&amp;nbsp;setting up macro vars1-n&amp;nbsp; for example &amp;amp;val1=Accident &amp;amp;val2=Accommodation &amp;nbsp;&amp;amp;val3=Additional etc etc&lt;/LI&gt;&lt;LI&gt;Loops through all the values &amp;nbsp;of &amp;amp;val1-n &amp;nbsp;to %sysfunc(TRANWRD) the ‘start’ values to the %sysfunc(PUTC) formatted value using the $abbreviations format. The tranwrd replaces all occurrences in the supplied string (ie the original column name) with the abbreviated value tp derive the short and meaningful value &lt;span class="lia-unicode-emoji" title=":smiling_face_with_smiling_eyes:"&gt;😊&lt;/span&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 15 Apr 2025 22:28:15 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/SAS-Format-contents-WITHOUT-running-a-proc-or-datastep-ie-pure/m-p/964378#M375589</guid>
      <dc:creator>robAs</dc:creator>
      <dc:date>2025-04-15T22:28:15Z</dc:date>
    </item>
    <item>
      <title>Re: SAS Format contents WITHOUT running a proc or datastep (ie pure macro)</title>
      <link>https://communities.sas.com/t5/SAS-Programming/SAS-Format-contents-WITHOUT-running-a-proc-or-datastep-ie-pure/m-p/964386#M375591</link>
      <description>&lt;P&gt;That does not sound like a task that requires a macro that does not run any SAS code.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Instead you should create a macro that takes input the name of the schema or table you want to be able to use and have it generate code to create a view (or perhaps a dataset) to that table using the shorter names.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Then the rest of the code just references that view.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;So essentially you want a macro that can generate code like:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;libname snowlib ..... connect to your schema in snowflake ....;
libname saslib 'some path on your SAS server';
proc sql;
connect using snowlib;
create view saslib.short_table_name as
select 
 short_name1 label='long_name1'
,short_name2 label='long_anme2'
from connection to snowlib
(select
 long_name1 as short_name1
,long_name2 as short_name2
from long_table_name
);
quit;&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Wed, 16 Apr 2025 02:30:36 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/SAS-Format-contents-WITHOUT-running-a-proc-or-datastep-ie-pure/m-p/964386#M375591</guid>
      <dc:creator>Tom</dc:creator>
      <dc:date>2025-04-16T02:30:36Z</dc:date>
    </item>
    <item>
      <title>Re: SAS Format contents WITHOUT running a proc or datastep (ie pure macro)</title>
      <link>https://communities.sas.com/t5/SAS-Programming/SAS-Format-contents-WITHOUT-running-a-proc-or-datastep-ie-pure/m-p/964392#M375592</link>
      <description>&lt;P&gt;I agree with &lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/159"&gt;@Tom&lt;/a&gt;&amp;nbsp;it would be better to create macro, that takes a tablename from Snowflake as input and then creates the corresponding SAS program code to create the view with the shorter names. You could use a DATA step to implement the logic. In the DATA step you write the code to a file which can then be executed using %INCLUDE ....; statement.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Find below an example for a macro that builds on your idea. It takes the individual parts of a long column name apart and uses a format to convert the individual parts to the short version. If a individual name can not be found in the format it simply stays the same.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc format;
  value $abbreviations 
    'Accident'     = 'Accdnt'
    'Accommodation' = 'Accm'
    'Additional'   = 'Addnl'
    'Admitted' = 'Admtd'
    'Admission' = 'Adm'
    'Agenda'  = 'Agnda'
    'Agent' = 'Agnt'
    'Ambulance' = 'Amb'
    'Amount'  = 'Amt'
    'Ancillary' ='Anc'  
  ;
run;

%macro abbreviate(longName, format=$abbreviations, dlm=_);
  %local i nParts tempPart newName;
  %let nParts = %sysfunc(countw(&amp;amp;longName, &amp;amp;dlm));

  %do i = 1 %to &amp;amp;nParts;
    %let tempPart = %scan(&amp;amp;longname, &amp;amp;i, &amp;amp;dlm);
    %let newName = &amp;amp;newName%sysfunc(putc(&amp;amp;tempPart, &amp;amp;format));

    %if &amp;amp;i &amp;lt; &amp;amp;nParts %then %do;
      %let newName = &amp;amp;newname&amp;amp;dlm;
    %end;
  %end;

  %put NOTE: &amp;amp;sysmacroname &amp;amp;=longName &amp;amp;=newname;
  &amp;amp;longName as &amp;amp;newName
%mend;

%put NOTE: *%abbreviate(Accident_Admitted_Agenda_Amount)*;
%put NOTE: *%abbreviate(Acc_Admitted_Agenda_Admission_cnt)*;&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Thu, 17 Apr 2025 12:12:53 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/SAS-Format-contents-WITHOUT-running-a-proc-or-datastep-ie-pure/m-p/964392#M375592</guid>
      <dc:creator>BrunoMueller</dc:creator>
      <dc:date>2025-04-17T12:12:53Z</dc:date>
    </item>
    <item>
      <title>Re: SAS Format contents WITHOUT running a proc or datastep (ie pure macro)</title>
      <link>https://communities.sas.com/t5/SAS-Programming/SAS-Format-contents-WITHOUT-running-a-proc-or-datastep-ie-pure/m-p/964684#M375684</link>
      <description>&lt;P&gt;I took Bruno's idea and kind of went a little crazy with it...&amp;nbsp; Here's a macro that I put together that will return the results of a user declared format from any available format library.&lt;BR /&gt;&lt;BR /&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT face="courier new,courier"&gt;%macro fmtlist (format) /des='returns all values of a format to a square bracket listing' ;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp;%local format sblout fmtname liblist numlib i library cntlout startlst endlst hlolst &lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; labellst&amp;nbsp;&lt;/FONT&gt;&lt;FONT face="courier new,courier"&gt;notes sascode rc start end hlo label dsid memname ;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp;%let sblout = %sysfunc(getoption(missing)) ;&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp;%if %length(&amp;amp;format)=0 %then %put NOTE: Argument 1 to macro function %nrstr(%FMTLIST) is missing or out of range. ;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp;%else %do ;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; %let format = %upcase(&amp;amp;format) ;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; %let fmtname = %sysfunc(compress(&amp;amp;format, %str($.))) ;&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; %let liblist = %translate(%sysfunc(getoption(fmtsearch)), ' ', '()') ;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; %let numlib = %sysfunc(countw(&amp;amp;liblist)) ;&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; %if &amp;amp;numlib = 0 %then &lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; %put NOTE: No libraries declared in SYSTEM OPTION FMTSEARCH=%sysfunc(getoption(fmtsearch)). ;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; %else %do i = 1 %to &amp;amp;numlib ;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;%let library = %scan(&amp;amp;liblist, &amp;amp;i, %str(%(%) )) ;&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;%if %cexist(&amp;amp;library..formats) %then %do ;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; %let cntlout = %nextdata(work) ;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; %let startlst = %str() ;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; %let endlst = %str() ;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; %let hlolst = %str() ;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; %let labellst = %str() ;&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; %let notes=%sysfunc(getoption(notes)) ;&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/FONT&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; %let sascode = %str(&lt;/FONT&gt;&lt;FONT face="courier new,courier"&gt;options nonotes ;&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; proc format library=&amp;amp;library cntlout=&amp;amp;cntlout (where=(upcase(fmtname)="&amp;amp;fmtname")) ;&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; run ;&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; options &amp;amp;notes;) ;&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; %let rc = %sysfunc(dosubl(%superq(sascode)&lt;/FONT&gt;&lt;FONT face="courier new,courier"&gt;)) ;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; %if %obscnt(&amp;amp;cntlout) &amp;gt; 0 %then %do ;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;%let dsid = %sysfunc(open(&amp;amp;cntlout)) ;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;%syscall set(dsid) ;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;%do %while (%sysfunc(fetch(&amp;amp;dsid)) = 0) ;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;%let startlst = &amp;amp;startlst {%strip(&amp;amp;start)} ;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;%let endlst = &amp;amp;endlst {%strip(&amp;amp;end)} ;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; %let labellst = &amp;amp;labellst {%strip(&amp;amp;label)} ;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; %if %length(&amp;amp;hlo) = 0 %then %let hlolst = &amp;amp;hlolst {.} ;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; %else %let hlolst = &amp;amp;hlolst {%strip(&amp;amp;hlo)} ;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;%end ;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;%let rc = %sysfunc(close(&amp;amp;dsid)) ; &lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;%let i = &amp;amp;numlib ;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;%let sblout = [LIBRARY: &amp;amp;library] [FMTNAME:%strip(&amp;amp;fmtname)] [START:%strip(&amp;amp;startlst)]&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; [END:%strip(&amp;amp;endlst)] [HLO:%strip(&amp;amp;hlolst)] [LABEL:%strip(&amp;amp;labellst)] ;&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;%let memname = %scan(&amp;amp;cntlout, 2) ;&lt;BR /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;%let sascode = %str(options nonotes ;&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;proc datasets library=work nolist ;&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; delete &amp;amp;memname ;&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;quit ;&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;options &amp;amp;notes ; ) ;&lt;BR /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;%let rc = %sysfunc(dosubl(%superq(sascode))) ;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; %end ;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;%end ;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; %end ;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp; &amp;nbsp;%superq(sblout)&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;%mend fmtlist ;&lt;/FONT&gt;&lt;BR /&gt;&lt;BR /&gt;Using Bruno's example format above, you could call it like this:&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;%put FORMATS=%fmtlist($gender) ;&lt;/FONT&gt;&lt;BR /&gt;&lt;BR /&gt;The results are:&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;90 %put FORMATS=%fmtlist($gender) ;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;FORMATS=[LIBRARY: WORK] [FMTNAME:GENDER] [START:{F} {M} {**OTHER**}] [END:{F} {M} {**OTHER**}] [HLO:{.} {.} {O}] [LABEL:{female} {male} {others}]&lt;/FONT&gt;&lt;BR /&gt;&lt;BR /&gt;I put these into a "square bracket listing" where the list is parsed and grouped first into square brackets and can be labeled with a colon marker, then braces inside the square brackets to group each&amp;nbsp; component of the list.&amp;nbsp; It's not perfect, but can work.&amp;nbsp; Choose your own delimiters, it won't bug me.&lt;BR /&gt;&lt;BR /&gt;You'll note that the returned value shows which LIBRARY the format was found, and it is searched in order declared in the&amp;nbsp;FMTSEARCH= option.&amp;nbsp; This way, if you have two libraries with the same named format in them, the value you get back will be the one that your program session will find as it goes through the different libraries in order.&lt;BR /&gt;&lt;BR /&gt;A few embedded macros I should explain:&amp;nbsp; %CEXIST is a variation of the CEXIST function and checks to confirm if a catalog exists.&amp;nbsp; %OBSCNT is my flavor of returning the observations of a data set.&amp;nbsp; %NEXTDATA returns the next availabe (unused) data set name in the given library (which is then deleted at the end of the macro).&amp;nbsp; %STRIP is simply a compressed version of %SYSFUNC(STRIP()), and %TRANSLATE is version of %SYSFUNC(TRANSLATE()).&lt;BR /&gt;&lt;BR /&gt;In just about every case, I do think it would be easier-faster-better-simpler to use CNTLOUT= on PROC FORMAT, or otherwise search catalogs. But this will do.&amp;nbsp;&lt;BR /&gt;&lt;BR /&gt;Your mileage my vary.&lt;/P&gt;&lt;P&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;/P&gt;</description>
      <pubDate>Sat, 19 Apr 2025 23:57:02 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/SAS-Format-contents-WITHOUT-running-a-proc-or-datastep-ie-pure/m-p/964684#M375684</guid>
      <dc:creator>PaulMcDonald-AZ</dc:creator>
      <dc:date>2025-04-19T23:57:02Z</dc:date>
    </item>
  </channel>
</rss>

