BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
Hari2
Quartz | Level 8

Hi All,

 

 

I have a lengthy comment getting into a macro variable from an external text file. Now, I am just writing the value of macro variable into a rtf file using PUT statement .

 

The requirement is, I need to  align the data properly and also it should fit in a box. Thanks in advance.

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
Cynthia_sas
SAS Super FREQ

Hi:
Most of what you describe can be produced by using a Macro program definition. Where I have my %let statements, you would have some kind of looping construct that would cause the program to create 1 RTF file for each of your subjects. That part is fairly straightforward.

Your requirement for suppressing null strings is easily done with IF statements, my program did not get that complicated, but instead of doing a simple CATX, as I show, you could include another test for the value of any line's macro variable to be missing or not. Something like this, if you were going to do your test inside a DATA step:
else if linenum = 5 then do;
    if "&stdt1" = " " then linestr = " ";
    else if "&stdt1" gt " " then linestr = catx(' ',linestr,"&stdt1")
end;

or, you might choose to make the test part of the macro code and use the presence or absence of the macro variable to determine the code that was written. That is more of a design approach.

For your question about having the comments in an Excel file, my suggestion would be that there are a couple of ways to deal with this. You could either read the subject file and the comment file separately and merge them together ahead of time (before your loop) so that you have the appropriate comment in the same data file with the subjects -- 100 subjects and 5 variables or 6 variables -- even lengthy strings is not going to be too big to process. Or, you could read the Excel file one time for each subject and extract only the comment you need for that subject inside the loop to produce the RTF file. My tendency would be to use the first approach. I'm a fan of getting all my data organized the way I want before I start a reporting step.

I envision 1 PROC REPORT step if you get all the data organized into 1 dataset. However, if the data is in 2 datasets and you need 2 different reports, then I would envision something like this:


** looping structure for each subject;

ods rtf file="&&subj&i..rtf" startpage=no;

** first proc report for main subject information;
** can use a WHERE statement to restrict the PROC REPORT to one subject;

** second proc report for information from Excel file, which you will;
** need to get into a SAS dataset before this step;
** can also use a WHERE statement to restrict the PROC REPORT to the comment ;
** for one subject;

ods rtf close;

** end looping structure;

It really comes down to what you feel comfortable with and what can be maintained over time. For example, you could want 2 types of report -- it's not clear to me what you might want to see produced. Here is an example:

not_clear.png

cynthia

View solution in original post

14 REPLIES 14
RW9
Diamond | Level 26 RW9
Diamond | Level 26

Examples?

 

There are two parts here, first importing the data from the text file into a SAS dataset.  I assume that is fine from your side?

 

Next is outputting to the RTF file, is there a reason you cannot use proc report - as that has border controls, alignment and such like built in, would make life a lot easier?

 

Or is it for a title, if so you can apply styles also to that.  Without some information its really hard to guess.

Hari2
Quartz | Level 8

Thanks for reply.

 

I am writing some data (specific columns for each subject which are fetched from a dataset into macro variables) already through PUT statement into a external RTF file. 

 

At last I have to append Comments (This value I will fetch it from a different file into a macro variable). I am trying to write the value from a macro variable using PUT statement after all columns printed through put statements as mentioned above.

for comments value, I need to display with proper alignment with in a box, just to look good. Now since comments value is a lengthy statement and its not getting displayed properly in the RTF file.

 

as you mentioned, we may try to display the macro variable with in TITLE/FOOTNTE statement with styles applied to it. please suggest how can we do this.  Just assume a macro variable with lengthy single statement in it as a value and we have to write to a RTF file and the value should be with in box.

 

Please consider &comm. has the value, you can see Put "&comm."; in the code below.

 

 

 

%MACRO AEDATA();

%DO i=1 %to &total.;

 

data _NULL_;

file "XXXXXXXXX\testf&i..rtf" print  ;

 

Title;

put ' ';

put ' ';

PUT 'SUBECT ID :' "&&sub&i.";

%IF %sysfunc(length("&&aetrm&i.")) > 2 %then %do;

put 'AE Term is :' "&&aetrm&i.";

%end;

%IF %sysfunc(length(&&llt&i.)) > 0 %then %do;

put 'AE Llt is :' "&&llt&i.";

%end;

put 'Start date is :' "&&stdt&i.";

put '*************************';

put '*************************';

put '*************************';

put '*************************';

put "&comm.";

 

run;

%END;

%MEND;

 

%aedata;

 

 

 

 

andreas_lds
Jade | Level 19

Without seeing any data it is difficult to suggest something, except: don't use macro language if you don't have to. RTF-files can be created by ods rtf, there is hardly any need to do this manually with data steps.

RW9
Diamond | Level 26 RW9
Diamond | Level 26

As @andreas_lds has said, its far simpler to use the tools built to generate outputs.

 

It looks to me like your creating some sort of patient profile as a text file.  You can achieve the same thing, just get all your data into a dataset and then use proc report - you can add borders, change fonts etc. and with ods rtf create an rtf file from it.  Just putting plain text out to a file, you would need to have a good level of RTF tagset knowledge to apply all the relevant tags.

Reeza
Super User

Look at PROC ODSTEXT.

Cynthia_sas
SAS Super FREQ

Or, in addition to Reeza's suggestion, you could use PROC REPORT to generate something like this:

text_in_box.png

Which was created using ODS RTF with PROC REPORT instead of using PUT statements.

 

Here's the sample code -- instead of putting the program in a loop, I just hardcoded values for the macro variables.

%let  sub1 = Lewis Carroll ;
%let  aetrm1 = Term 1 ;
%let  llt1 = Something Else ;
%let  stdt1 = January 4, 2018 ;
%let  comm1= %str(Twas brillig and the slithy toves did gyre and gimble in the wabe. All mimsy were the borogroves and the momeraths outgrabe.);

data comment;
  length linestr $1000;
  infile datalines dlm=',' dsd;
  input linenum linestr $;
  if linenum = 1 then linestr = catx(' ',linestr,"&sub1");
  else if linenum = 3 then linestr = catx(' ',linestr,"&aetrm1");
  else if linenum = 4 then linestr = catx(' ',linestr,"&llt1");
  else if linenum = 5 then linestr = catx(' ',linestr,"&stdt1");
  else if linenum = 7 then linestr = catx(' ',linestr,"&comm1");
return;
datalines;
1,'^{style[fontweight=bold]SUBECT ID:}'  
2,'^{newline 2}'
3,"^{style[fontweight=bold]AE Term is:} "
4,"^{style[fontweight=bold]AE Llt is:}"
5,"^{style[fontweight=bold]Start date is:}"
6,"*************************"
7,"^{style[fontweight=bold]Comment:}"
;
run;

ods escapechar='^';
options nodate number;
title;

ods rtf file="c:\temp\testf1.rtf" style=rtf;

  proc report data=comment noheader
      style(report)={rules=none frame=box cellspacing=0 width=5in};
  column linenum linestr;
  define linenum / order noprint;
  define linestr / display;
  run;

ods rtf close;
 

Cynthia

Hari2
Quartz | Level 8

HI Cynthia,

 

Thanks a lot for your inputs.

 

I will give what exactly my requirement is,

 

1. I have a data set with 100 subjects and 5 variables.

2. For each subject I have to display a separate RTF file with the actual data as per data set in the format that you gave in the

    previous reply. Also For ex: if there is any field, lets assume 'Start date' is one of the fields and for a specific subject start date is  

    Null, we should not get that row at all in the rtf file.

3. At last, I have another Excel input where we get reviewer comments in it in a single cell and it could be very lengthy. I have to

   append those comments to the respective RTF file subject wise with a neat text alignment and borders to it (Comments should be With in a BOX at the end of the RTF file for each subject with proper format).

 

 

please help me on this requirement.

 

Thanks,

Hari

Cynthia_sas
SAS Super FREQ

Hi:
Most of what you describe can be produced by using a Macro program definition. Where I have my %let statements, you would have some kind of looping construct that would cause the program to create 1 RTF file for each of your subjects. That part is fairly straightforward.

Your requirement for suppressing null strings is easily done with IF statements, my program did not get that complicated, but instead of doing a simple CATX, as I show, you could include another test for the value of any line's macro variable to be missing or not. Something like this, if you were going to do your test inside a DATA step:
else if linenum = 5 then do;
    if "&stdt1" = " " then linestr = " ";
    else if "&stdt1" gt " " then linestr = catx(' ',linestr,"&stdt1")
end;

or, you might choose to make the test part of the macro code and use the presence or absence of the macro variable to determine the code that was written. That is more of a design approach.

For your question about having the comments in an Excel file, my suggestion would be that there are a couple of ways to deal with this. You could either read the subject file and the comment file separately and merge them together ahead of time (before your loop) so that you have the appropriate comment in the same data file with the subjects -- 100 subjects and 5 variables or 6 variables -- even lengthy strings is not going to be too big to process. Or, you could read the Excel file one time for each subject and extract only the comment you need for that subject inside the loop to produce the RTF file. My tendency would be to use the first approach. I'm a fan of getting all my data organized the way I want before I start a reporting step.

I envision 1 PROC REPORT step if you get all the data organized into 1 dataset. However, if the data is in 2 datasets and you need 2 different reports, then I would envision something like this:


** looping structure for each subject;

ods rtf file="&&subj&i..rtf" startpage=no;

** first proc report for main subject information;
** can use a WHERE statement to restrict the PROC REPORT to one subject;

** second proc report for information from Excel file, which you will;
** need to get into a SAS dataset before this step;
** can also use a WHERE statement to restrict the PROC REPORT to the comment ;
** for one subject;

ods rtf close;

** end looping structure;

It really comes down to what you feel comfortable with and what can be maintained over time. For example, you could want 2 types of report -- it's not clear to me what you might want to see produced. Here is an example:

not_clear.png

cynthia

Hari2
Quartz | Level 8
Thanks a Lot Cynthia. 🙂
Cynthia_sas
SAS Super FREQ
You're welcome! BTW, I'm not entirely sure you need to have extensive macro variables for each subject. I created some fake data for the 2 screen shots and did use a macro program for the looping, but did NOT use macro variables to write the values in the box -- I just used regular DATA set variables in a concatenate. I found I did not really need macro variables.

And, as others have explained in regard to your other posting about "appending" to an RTF file. It is very, very hard to create an RTF file and then append any addition output to it. It is far easier to have 1 ODS RTF "sandwich" which captures the output from the first procedure or step and then captures the output from the next procedure or step and puts both outputs into 1 ODS RTF file.

cynthia

cynthia
Hari2
Quartz | Level 8
HI Cynthia,

in the above code which you suggested, How to align any specific line in Center.
ex: I want to keep data in first line in CENTER. please provide which option to use. Please reply as soon as you see this. Thanks in advance.
Cynthia_sas
SAS Super FREQ

Hi:
Without seeing YOUR code, it's hard to suggest how to center the first line. There were 2 different programs for 2 different reports in my screen shot. Basically, I'd need to do a style override and use JUST=C in the style override. But depending on this example you're asking about, I might make the change in an ODS ESCAPECHAR style override or I might have a style override in a DEFINE statement or might have it in a CALL DEFINE statement.

For the program that I used to make that example back in January, I would have needed a CALL DEFINE because I used a LINENUM variable to identify each string on the report. So in example #2 (on the right), I would have needed to do this:
how_to_center.png

In this example, I used 2 PROC REPORTs to generate the output. The SUBJECT ID: line would need to be centered with a style override in a CALL DEFINE in my program.
Cynthia

Hari2
Quartz | Level 8

Thanks Cynthia. This is what I was expecting and It was helpful.

 

One more , I actually used Background color , however its coming entire line in the page. I want to restrict it only to the Text that is available . Could you please suggest how to make it.

 

Ex: My Output should have first line with Heading as "Your Complete Details" aligned Center with some Background color and BG Color should only fit to the Text not the entire Line.

 

 

 

 

 

 

 

 

Hari2
Quartz | Level 8
Thanks Cynthia. This is what I was expecting and It was helpful.



One more , I actually used Background color , however its coming entire line in the page. I want to restrict it only to the Text that is available . Could you please suggest how to make it.



Ex: My Output should have first line with Heading as "Your Complete Details" aligned Center with some Background color and BG Color should only fit to the Text not the entire Line.

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

Register now!

How to Concatenate Values

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 14 replies
  • 1702 views
  • 2 likes
  • 5 in conversation