I have delimiter separated data values that are generated like this:
abc|def ghi|jkl
mno|pqr|stu||vw
x|y|z
How do I get all of these into one observation? I also have the the column names in input statement. Can someone please help. Thank you.
You cannot use CARDS (aka DATALINES) inside a macro. The macro processor parses the lines and "ruins" them for the SAS processor. You have demonstrated that when you execute a macro via CALL EXECUTE you can circumvent that restriction. When CALL EXECUTE() pushed the string to SAS to put on the stack it runs the macro immediately and pushes the generated text onto the stack for the SAS processor. When the SAS processor pulls the generated code back off of the stack it does not treat it as being in a macro. Which makes sense because by the time the data step ends and SAS starts trying to interpret the code from the stack the macro has ended execution already.
The reason you get LOST CARD message is because you haven't given the data step any lines of data. When you use CARDS in-line data stops BEFORE the first line that contains a semi-colon. Since the macro processor/call execute combination does not generate lines you get something like:
data want; input x y ; datalines; 1 2;
So there is no data there.
Either parse the string yourself.
Or if you want to use the INPUT statement then create a temporary file and put the text in there and read from there.
%macro createDS(dsname, colnames, colvalues);
filename lines temp;
data _null_;
file lines;
put "&colvalues";
run;
data &dsname;
length &colnames $1000;
infile lines dlm='|' dsd ;
input &colnames @@;
run;
filename lines;
%mend createDS;
options mprint;
%createDS(xxx,name value,a|100|b|200|c|300);
proc print;
run;
Obs name value 1 a 100 2 b 200 3 c 300
What do you mean by "one observation"? How many columns should the dataset have, and what should they contain?
Thank you @Kurt_Bremser. Basically, I have column names and column values that are generated dynamically and I pass that as macro variable for a dataset creation. Column values always have data for one row.
And I pass those values inside a macro variable and when it resolves, it actually spans multiple lines after datalines. But I want that as one row.. I tried @@/truncover but it's not helping.
So what should the dataset look like for this input:
abc|def ghi|jkl mno|pqr|stu||vw x|y|z
?
Problem is when the column values resolve from a macro variable it's getting split into new lines within the datalines...
So it seems you have line breaks right within columns, but nothing to recognize them. This cannot be handled reliably.
The only way one can work around such things is if the "non-natural" line breaks look different form those that actually separate records.
@AshleyBright wrote:
But it's actually resolving like this during the macro variable resolution.. Is there a way we can resolve the macro variable in one line to make the data step read the dataline as one whole record?
Post your code & log, as @PaigeMiller requested.
Two suggestions ...
First, make sure the INFILE statement uses DSD:
infile datalines dlm='|' dsd;
Second, is it possible to simplify the INPUT statement:
input (col1-col9) ($);
Get rid of @@, get rid of TRUNCOVER, and be willing to accept a message that SAS went on to a new line when it reached past the end of the current line.
If that's not possible, you will need to provide an example of the names of the macro variables and what each contains,. You might be able to use:
input (&maclist1. &maclist2. &maclist3.) ($);
I have a macro variable that holds column values that I use after datalines statement. When the macro variable is resolved, I can see that it is splitting into different lines in the log which is causing problem. It should all be read as one single row. Can someone please help. Thanks.
Show us your code. (Click on the running man icon and paste the code into that window. Do not skip this step.)
Show us the SASLOG. (Click on the {i} icon and paste the log into that window. Do not skip this step.)
%macro createDS(dsname, colnames, colvalues);
data &dsname;
attrib &colnames length = $1000;
infile datalines dlmstr='|';
input &colnames @@;
datalines;
&colvalues
;
run;
%mend createDS;
data test;
set raw;
call execute('%createDS('||dsn||','||columns||','||values||');');
run;
Macro references are not resolved in datalines, and datalines are not valid in macros. The log will alert you to that.
Based on this program ...
get rid of @@. It's not hurting anything, but it's not helping either.
Since you give your variables a length of $1000, I am tempted to think you might have some long values there ... values that might be affected by the number of characters that SAS will read. So first, try this INFILE statement:
infile datalines dlm='|' dsd lrecl=9000;
That will let SAS read beyond the normal (256?) character limit when reading in data.
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.
Ready to level-up your skills? Choose your own adventure.