DATA Step, Macro, Functions and more

Reading inline data with a macro

Accepted Solution Solved
Reply
Respected Advisor
Posts: 4,649
Accepted Solution

Reading inline data with a macro

Hi, I would like to read inline paragraphs into a dataset at the beginning of my SAS programs. How can I automate this operation with a macro.? So far, I get an error when the macro processor expands the datalines4 statement in :

 

%macro docu;
data docu;
length id $32 text $2000;
retain id text;
infile datalines eof=eof;
input;
if first(_infile_) = "@" then do;
    if not missing(id) then output;
    id = substr(_infile_, 2);
    call missing(text);
    end;
else text = catx(" ", text, _infile_);
return;
eof: if not missing(id) then output;
datalines4;
%mend docu;

%docu;
@c1
Comment Comment Comment Comment Comment Comment 
Comment Comment Comment Comment Comment 
Comment Comment Comment 
Comment Comment 
Comment 
@c2
Comment 
;;;;

What else can I do?

PG

Accepted Solutions
Solution
‎03-27-2016 02:13 PM
PROC Star
Posts: 1,231

Re: Reading inline data with a macro

Agree with @Ksharp's suggetion to move the data to a file.

 

I misread your post, and thought that you were okay with having the data itself outside of the macro definition (immediately after the macro call).  If that were the case, you could remove the DATALINES statement from the macro definition as well, and add it after the call, e.g.:

%docu;
datalines4;
@c1
Comment Comment Comment Comment Comment Comment 
Comment Comment Comment Comment Comment 
Comment Comment Comment 
Comment Comment 
Comment 
@c2
Comment 
;;;;

 

Which looks a bit odd, but works.

View solution in original post


All Replies
Super User
Posts: 9,681

Re: Reading inline data with a macro

PG,
If I was right, you can't use CARDS or DATALINES in a Macro.
Try to make a file instead.

Super User
Posts: 3,106

Re: Reading inline data with a macro

[ Edited ]

This is an explicit SAS restriction:

 

http://support.sas.com/kb/43/902.html

 

@Ksharp's suggestion of an external file is an alternative approach.

Solution
‎03-27-2016 02:13 PM
PROC Star
Posts: 1,231

Re: Reading inline data with a macro

Agree with @Ksharp's suggetion to move the data to a file.

 

I misread your post, and thought that you were okay with having the data itself outside of the macro definition (immediately after the macro call).  If that were the case, you could remove the DATALINES statement from the macro definition as well, and add it after the call, e.g.:

%docu;
datalines4;
@c1
Comment Comment Comment Comment Comment Comment 
Comment Comment Comment Comment Comment 
Comment Comment Comment 
Comment Comment 
Comment 
@c2
Comment 
;;;;

 

Which looks a bit odd, but works.

Respected Advisor
Posts: 4,649

Re: Reading inline data with a macro

Thank you @Ksharp@SASKiwi@Quentin. My first idea was to move the comments to a separate file, as you suggested. But I want the comments to be strongly bound to the program (analysis). If the program could somehow find the comments by itself, e.g. program toto.sas reads comments toto.txt in the same directory, that would be good enough for me. I tried to implement that, but got stuck when trying to get the path and filename of the program currently running. I'd be really pleased if anybody knew a way to get that info.

 

I think I'll go with Quentin's suggestion to move the datalines4 outside the macro. 

PG
Trusted Advisor
Posts: 1,115

Re: Reading inline data with a macro

Hi PG,

 

I take it that those "inline paragraphs" are individual text that you would type, say, into the Enhanced Editor and you would like to read this text into the DOCU dataset using your macro. (I don't know how WORK.DOCU would be "bound to the program (analysis)," though, but I assume you have prepared something to establish this connection.)

 

So, how about this:

  1. Slightly modify your code to let SAS read the text from the clipboard: filename clippy clipbrd; ... infile clippy eof=eof; ... run;
  2. Save the program code (not necessarily as a macro) or the macro call somewhere, e.g., as C:\Temp\docu.sas.
  3. Enter an appropriate SUBMIT command into the KEYS window, e.g. 
F12    submit "%inc 'C:\Temp\docu.sas';"

 

Now, the procedure would be:

  1. Type the comment text,
  2. select it,
  3. copy it to the clipboard (Ctrl-C),
  4. hit F12 (in SAS). 

If you type the text into a Program Editor (not Enhanced Editor) window, you can omit step 3 by adding the STORE command before the SUBMIT command in the key definition. (If someone knows how to get this to work with the Enhanced Editor, please post it here. To me it seems that the Enhanced Editor macros on the one hand can't submit code and the DM commands STORE and WCOPY on the other hand do not work for the Enhanced Editor.)

 

PROC Star
Posts: 1,231

Re: Reading inline data with a macro

Hi PG,

 

Glad it helped.  re finding the path and name of the currently executing program, how are your running it  (PC SAS interactive/batch, EG, SAS Studio, etc?)  Usually there is a way.  In PC SAS interactive, I use %qsysfunc(sysget(SAS_EXECFILEPATH)).  In PC SAS batch, I use %qsysfunc(getOption(SYSIN)).  In EG I can get the path to the project file, not sure about the program.  In DI Studio it takes some processing of the metadata, but it's in there...

 

I'm not quite seeing the big picture of what you are doing.  But I wrote a paper about parsing program headers to pull data from them.  http://www.lexjansen.com/nesug/nesug04/po/po04.pdf .   I haven't done it before, but it looks like a .sas program can read itself (i.e. the .sas file) as data.  In interactive PC SAS, if I save the following code as a .sas file and submit it, it reads itself and writes the comment to the log.

 

/***
COMMENT: Hi Mom
***/

data _null_;
  infile "%qsysfunc(sysget(SAS_EXECFILEPATH))";
  input;
  if _infile_ =: "COMMENT:" then put _infile_;
run;

 

So something like that could be another approach, if you want to parse text from the current .sas program.

 

--Q.

Respected Advisor
Posts: 3,777

Re: Reading inline data with a macro

[ Edited ]

PARMCARDS is a global statement.

 

Put this in and auto call library.

 

options parmcards=FT77F001;
filename FT77F001 temp;
parmcards4;
This is the comment
This is the comment
This is the comment
This is the comment
;;;;
options parmcards=FT15F001;
%macro pgstats(arg);
   data _null_;
      infile FT77F001;
      input;
      put _infile_;
      run;
   %put NOTE: Did it work;
   proc print data=sashelp.class;
      run;
   %mend pgstats;

And this is what you get

 

46         %pgstats();
MPRINT(PGSTATS):   data _null_;
MPRINT(PGSTATS):   infile FT15F001;
MPRINT(PGSTATS):   input;
MPRINT(PGSTATS):   put _infile_;
MPRINT(PGSTATS):   run;

NOTE: The infile FT15F001 is:
      (system-specific pathname), 
      (system-specific file attributes)

This is the comment
This is the comment
This is the comment
This is the comment
NOTE: 4 records were read from the infile (system-specific pathname).
      The minimum record length was 19.
      The maximum record length was 19.
NOTE: DATA statement used (Total process time):
      real time           0.15 seconds
      cpu time            0.03 seconds
      

NOTE: Did it work
MPRINT(PGSTATS):   proc print data=sashelp.class;
MPRINT(PGSTATS):   run;

NOTE: PROCEDURE PRINT used (Total process time):
      real time           0.07 seconds
      cpu time            0.06 seconds
      

 

It doesn't have to be in a macro but a self documenting autocall macro seems more interesting. 

☑ This topic is SOLVED.

Need further help from the community? Please ask a new question.

Discussion stats
  • 7 replies
  • 571 views
  • 4 likes
  • 6 in conversation