BookmarkSubscribeRSS Feed
acordes
Rhodochrosite | Level 12

I want to include sas code as text in a ODS pdf / proc odstext setting.

 

For that purpose I'd like to use a macro variable. 

 

FILENAME msghtml FILESRVC FOLDERPATH='/Projects/SAS Viya training VWFS/'  FILENAME='assign_brand.txt';
data _null_;
   length text $32767;

   retain text '';
   infile msghtml flowover  end=last;
   input;
   text=cats(text,_infile_);
   if last then call symput('MSGBODY2',text);
run;

%put %nrquote(&MSGBODY2.);

%let user1=Arne;

proc odstext;
p "&user1.";
p "&MSGBODY.";
run;

If I comment the second P line in the proc odstext, it works. 

Else it returns a blank window with the note:

NOTE: The quoted string currently being processed has become more than 2000 bytes long. You might have unbalanced quotation marks.

 

 

The macro variable resolves to:

82 %put %nrquote(&MSGBODY2.);
options VALIDMEMNAME=EXTEND VALIDVARNAME=ANY;length '_va_c_Marca'n $60;'_va_c_Marca'n=(KSCAN('DESC_TMAIMG_ES'n,1));;length
'_va_c_Marca_ok'n $10;if (('_va_c_Marca'n IN
('DIAVEL','DUACTI','Ducati','MULTISTRADA','DUCATI','MONSTER','SCRAMBLER','STREETFIGHTER')))then do;'_va_c_Marca_ok'n=
'Ducati';end;else do;if (('_va_c_Marca'n IN ('VOLKLSWAGEN','POLO','VOLKSWAGEB','VOLKSWAGEN','VOLSKWAGEN','VW')))then
do;'_va_c_Marca_ok'n= 'Volkswagen';end;else do;if (('_va_c_Marca'n IN ('TAYCAN','911','CARRERA','718','PANAMERA','PORSCHE')))then
do;'_va_c_Marca_ok'n= 'Porsche';end;else do;if (('_va_c_Marca'n IN ('A1','A3','A4','A5','A8','AUDI')))then do;'_va_c_Marca_ok'n=
'Audi';end;else do;'_va_c_Marca_ok'n= 'Other';end;end;end;end;;length _strfmt_ $60; drop _strfmt_;_strfmt_ = ' ';array
_tlevname_491_{5} $10 _temporary_ ( 'Audi''Ducati''Other''Porsche''Volkswagen');array _dt_fi_491_{5} _temporary_;_node_id_ =
0;_new_id_ = -1;nextnode_491:if _node_id_ eq 0 then do;_strfmt_ = left(trim(put(_va_c_Marca,$60.)));if _strfmt_ in
('LCV','PORSCHE','718','E','T','911','MII','CARRERA','ATECA','FABIA','COCHES','MS','MACAN','TAYCAN','PANAMERA','SEMINUEVO','MULTIVAN
','GOLD','MAN','CADDY','SEAT','CAYMAN','CAYENNE','CRAFTER','GOLF','CALIFORNIA','NEW','CUPRA','REFIN','SKODA','VARIOS') then
do;_new_id_ = 1;end;else if _strfmt_ in ('POLO','VW','VOLKLSWAGEN','VOLKSWAGEB','VOLKSWAGEN','VOLSKWAGEN') then do;_new_id_ =
2;end;else if _strfmt_ in ('AUDI','A3','A1','A4','A8','A5') then do;_new_id_ = 3;end;else if _strfmt_ in
('MONSTER','SCRAMBLER','DIAVEL','STREETFIGHTER','DUACTI','MULTISTRADA','DUCATI','Ducati') then do;_new_id_ = 4;end;else do;_new_id_
= 1;end;end;else if _node_id_ eq 1 then do;_strfmt_ = left(trim(put(_va_c_Marca,$60.)));if _strfmt_ in
('LCV','E','T','MII','ATECA','FABIA','COCHES','MS','MACAN','SEMINUEVO','MULTIVAN','GOLD','MAN','CADDY','SEAT','CAYMAN','CAYENNE','CR
AFTER','GOLF','CALIFORNIA','NEW','CUPRA','REFIN','SKODA','VARIOS') then do;_new_id_ = 5;end;else if _strfmt_ in
('PORSCHE','718','911','CARRERA','TAYCAN','PANAMERA') then do;_new_id_ = 6;end;else do;_new_id_ = 5;end;end;else if _node_id_ eq 2
then do;_leaf_id_ = 2;_new_id_ = -1;_dt_pred_lev_ = 4;_dt_pred_prob_ = 1;_dt_fi_491_{1} =
0;_dt_fi_491_{2} = 0;_dt_fi_491_{3} = 0;_dt_fi_491_{4} = 0;_dt_fi_491_{5}
= 1;end;else if _node_id_ eq 3 then do;_leaf_id_ = 3;_new_id_ = -1;_dt_pred_lev_ = 0;_dt_pred_prob_ =
1;_dt_fi_491_{1} = 1;_dt_fi_491_{2} = 0;_dt_fi_491_{3} =
0;_dt_fi_491_{4} = 0;_dt_fi_491_{5} = 0;end;else if _node_id_ eq 4 then do;_leaf_id_ =
4;_new_id_ = -1;_dt_pred_lev_ = 1;_dt_pred_prob_ = 1;_dt_fi_491_{1} = 0;_dt_fi_491_{2} =
1;_dt_fi_491_{3} = 0;_dt_fi_491_{4} = 0;_dt_fi_491_{5} =
0;end;else if _node_id_ eq 5 then do;_leaf_id_ = 5;_new_id_ = -1;_dt_pred_lev_ = 2;_dt_pred_prob_ =
1;_dt_fi_491_{1} = 0;_dt_fi_491_{2} = 0;_dt_fi_491_{3} = 1;_dt_fi_491_{4}
= 0;_dt_fi_491_{5} = 0;end;else if _node_id_ eq 6 then do;_leaf_id_ = 6;_new_id_ =
-1;_dt_pred_lev_ = 3;_dt_pred_prob_ = 1;_dt_fi_491_{1} = 0;_dt_fi_491_{2} =
0;_dt_fi_491_{3} = 0;_dt_fi_491_{4} = 1;_dt_fi_491_{5} = 0;end;if
_new_id_ >= 0 then do;_node_id_ = _new_id_;goto nextnode_491;end;I__va_c_Marca_ok = _tlevname_491_{_dt_pred_lev_+1};label
I__va_c_Marca_ok = 'Into: _va_c_Marca_ok';_i_ = 1;_dt_predp_ = _dt_fi_491_{_i_};P__va_c_Marca_okAudi = _dt_predp_;label
P__va_c_Marca_okAudi = 'Predicted: _va_c_Marca_ok=Audi';_i_+1;_dt_predp_ = _dt_fi_491_{_i_};P__va_c_Marca_okDucati =
_dt_predp_;label P__va_c_Marca_okDucati = 'Predicted: _va_c_Marca_ok=Ducati';_i_+1;_dt_predp_ =
_dt_fi_491_{_i_};P__va_c_Marca_okOther = _dt_predp_;label P__va_c_Marca_okOther = 'Predicted:
_va_c_Marca_ok=Other';_i_+1;_dt_predp_ = _dt_fi_491_{_i_};P__va_c_Marca_okPorsche = _dt_predp_;label P__va_c_Marca_okPorsche =
'Predicted: _va_c_Marca_ok=Porsche';_i_+1;_dt_predp_ = _dt_fi_491_{_i_};P__va_c_Marca_okVolkswagen = _dt_predp_;label
P__va_c_Marca_okVolkswagen = 'Predicted: _va_c_Marca_ok=Volkswagen';_i_+1;drop _dt_predp_;drop _i_;drop _dt_pred_lev_;drop
_dt_pred_prob_;drop _node_id_;drop _new_id_; drop '_va_c_Marca_ok'n '_va_c_Marca'n 'I__va_c_Marca_ok'n '_leaf_id_'n
'P__va_c_Marca_okAudi'n 'P__va_c_Marca_okDucati'n 'P__va_c_Marca_okOther'n 'P__va_c_Marca_okPorsche'n
'P__va_c_Marca_okVolkswagen'n;length 'I__va_c_Marca_ok_491_2'n
$10;'I__va_c_Marca_ok_491_2'n='I__va_c_Marca_ok'n;'P__va_c_Marca_okAudi_491_2'n='P__va_c_Marca_okAudi'n;'P__va_c_Marca_okDucati_491_
2'n='P__va_c_Marca_okDucati'n;'P__va_c_Marca_okOther_491_2'n='P__va_c_Marca_okOther'n;'P__va_c_Marca_okPorsche_491_2'n='P__va_c_Marc
a_okPorsche'n;'P__va_c_Marca_okVolkswag_491_2'n='P__va_c_Marca_okVolkswagen'n;'_leaf_id__491_2'n='_leaf_id_'n;

 

10 REPLIES 10
PaigeMiller
Diamond | Level 26
NOTE: The quoted string currently being processed has become more than 2000 bytes long. You might have unbalanced quotation marks.

This often happens when you do have earlier in your program a missing quotation mark. Best to try re-starting SAS and see if the program works.

 

Which brings me to a question. Why do you make your life much more difficult with variable names such as '_va_c_Marca'n?? It seems as if all of your variable names have the quotation marks and suffix N? This is difficult to type and could be the cause of your unbalanced quotation marks. And its completely unnecessary here, when the variable name _va_c_Marca would work just as well.

 

However ... from now on, when there are problems in the log, we expect you will provide the log in the proper code box ... copy the log as text, paste it into the window that appears when you click on the </> icon. No exceptions from now on.

 

Insert Log Icon in SAS Communities.png

--
Paige Miller
acordes
Rhodochrosite | Level 12

OK, understood. I'll use the text box from now on. 

 

The variable name convention is directly created from Visual Analytics when exporting a model, here a decision tree. 

 

acordes
Rhodochrosite | Level 12

Changing the txt file thus the macro variable doesn't resolve this issue either. 

 

The macro variable resolves to:

%put %nrquote(&MSGBODY2.);
Der Pissbahnhof-Vergleich hat Ludwigshafen dann doch geschmerzt. An öde Witze (Was ist das Schönste an Ludwigshafen? Die Brücke 
nach Mannheim!) und Schmähungen des Stadtbilds ( Betonversessene Planierraupen-Architektur ) ist man ja gewöhnt in der Heimstatt 
des weltgrößten Chemiekonzerns BASF. Dass der SWR seinen Odenthal-Tatort lieber in Baden-Baden dreht, obwohl er in Ludwigshafen 
spielt, wird achselzuckend hingenommen.Aber der Verriss im  Spiegel , dessen Reporter nach Helmut Kohls Tod im Sommer 2017 ein 
knappes Stündchen durch die City geirrt war, empörte dann doch. Eine verwahrloste Geisterstadt sei Ludwigshafen, geeignet als 
Kulisse für osteuropäische Agentenfilme aus den 60ern:  Verglichen mit dem Zentrum von Ludwigshafen wirkte jeder Pissbahnhof in 
Vorpommern, jede Autobahntankstelle in Sachsen-Anhalt wie ein blühender Zukunftsort.Als der Geburtsort von Helmut Kohl und Ernst 
Bloch, von André Schürrle und Daniela Katzenberger kurz darauf auch noch zur  hässlichsten Stadt Deutschlands  gekürt wurde, 
wenn auch nur von der TV-Satiresendung  Extra 3 , hielt das Kulturamt die Zeit gekommen für eine gepfefferte Replik. Man 
aktivierte den Performance-Künstler Helmut van der Buchholz. Der leitet seither Rundgänge und Radtouren – zu den schlimmsten, 
unansehnlichsten, peinlichsten Ecken der Stadt. Ihr Titel:  Germany’s Ugliest City Tours .                                        

(text copied from https://www.welt.de/reise/staedtereisen/article243102677/Ludwigshafen-Eine-Tour-durch-die-haesslichs... )

But the ods output is not generated. That's true as well for wrapping a ods pdf statement around it. The pdf is still blank. 

%let user1=Arne;

proc odstext;
p "&user1.";
p "%nrquote(&MSGBODY2.)";
run;

 

PaigeMiller
Diamond | Level 26

I think we need to see all of the log, before you get to PROC ODSTEXT as well as the log from within PROC ODSTEXT.

--
Paige Miller
acordes
Rhodochrosite | Level 12

When I use this code

ods pdf file="/caslibs/marketing/&tab._topn.pdf" style=Style.Custom;
ods escapechar='^';

%let user1=Arne;
FILENAME refy FILESRVC FOLDERPATH='/Projects/SAS Viya training VWFS/'  FILENAME='pic.png';
proc odstext;
p "&user1.";
/* p "%nrquote(&MSGBODY2.)"; */
P '^{style [preimage=refy}';
run;

ods pdf close;

the final pdf looks correct, with the macro variable user1 resolved to Arne and the image inserted.

 

If I comment the preimage line and uncomment the problematic macro variable line, the output is blank. 

Thank you, the log. 

1    %studio_hide_wrapper;
82   %studio_show_only_notes_wrapper;
NOTE: ODS statements in the SAS Studio environment may disable some output features.
85   ods pdf file="/caslibs/marketing/&tab._topn.pdf" style=Style.Custom;
WARNING: Apparent symbolic reference TAB not resolved.
WARNING: Style STYLE.CUSTOM not found; Pearl style will be used instead.
NOTE: Writing ODS PDF output to DISK destination "/caslibs/marketing/&tab._topn.pdf", printer "PDF".
86   ods escapechar='^';
87   
88   %let user1=Arne;
89   FILENAME refy FILESRVC FOLDERPATH='/Projects/SAS Viya training VWFS/'  FILENAME='pic.png';
90   proc odstext;
91   p "&user1.";
92   p "&MSGBODY2.";
NOTE: The quoted string currently being processed has become more than 2000 bytes long.  You might have unbalanced quotation marks.
93   /* P '^{style [preimage=refy}'; */
94   run;
NOTE: PROCEDURE ODSTEXT used (Total process time):
      real time           0.69 seconds
      cpu time            0.72 seconds
      
95   
96   ods pdf close;
NOTE: ODS PDF printed 1 page to /caslibs/marketing/&tab._topn.pdf.
97   
98   %studio_hide_wrapper;
109  
110  

 

 

PaigeMiller
Diamond | Level 26

I think you need to fix this:

 

WARNING: Apparent symbolic reference TAB not resolved.
--
Paige Miller
s_lassen
Meteorite | Level 14

There does not seem to be any problems with the code in the macro variable (no double quotes inside, so it should work as a paragraph). So the problem may be with the length of the string, probably that you use CALL SYMPUT, with a string that has the maximum length, so the macro variable will get a length of 32767 characters (with probably quite a lot of blanks in the end). 

 

If you change the call to CALL SYMPUTX (which trims blanks at the end), it may work.

 

Another possibility is to create a temporary file with statements for PROC ODSTEXT, and %INCLUDE that:

FILENAME msghtml FILESRVC FOLDERPATH='/Projects/SAS Viya training VWFS/'  FILENAME='assign_brand.txt';
filename temp temp;
data _null_;
   infile msghtml flowover  end=last;
   input;
   file temp;
   put 'p ' _infile_ $quote200. ';';
run;

proc odstext;
  p "&user1";
  %include temp;
run;
acordes
Rhodochrosite | Level 12

Thanks @s_lassen , it works like a charm

Tom
Super User Tom
Super User

Why are you trying to write the whole file into one ODSTEXT paragraph?  Wouldn't that generate unformatted gibberish (kind of like posting code into the main body of response on this forum)?

FILENAME msghtml FILESRVC FOLDERPATH='/Projects/SAS Viya training VWFS/'  FILENAME='assign_brand.txt';
filename code tmep;

data _null_;
   infile msghtml end=last;
   file code ;
   input;
   put 'P ' _infile_ :$quote. ';' ;
run;

%let user1=Arne;

proc odstext;
p "&user1.";
%include code / source2;
run;

 

acordes
Rhodochrosite | Level 12

I'm happy, that's exactly what I need @Tom 

 

I cannot mark your reply as a solution. I don't know why. Sorry

SAS Innovate 2025: Call for Content

Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!

Submit your idea!

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
  • 10 replies
  • 1579 views
  • 3 likes
  • 4 in conversation