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

Your log indicates that 29 observations were printed somewhere.

AshleyM
Fluorite | Level 6

Yes, and I'm not sure where it was printed.

The stored process allows me to choose Standard HTML, PDF, download HTML to microsoft excel, download HTML to Microsoft Word. I assume I'll need to add a print macro variable for those options.

NN
Quartz | Level 8 NN
Quartz | Level 8

Hi,

Have you selected Stored Prooces Server in your STP options. and Checked the Streaming Output Option..?

AshleyM
Fluorite | Level 6

For the stored process I created a prompt for "_odsdest. " Then, for the prompt type and values I specified HTML, PDF, Microsoft Excel and Microsoft Word.

I can generate the HTML and PDF formats using this code below, but am uncertain how to export data to excel and/or word. Would a simple proc export work or should I add additional language here?

*ProcessBody;

%stpbegin;

proc print data=work.test;

run;

%stpend;

NN
Quartz | Level 8 NN
Quartz | Level 8

Read this sasnote it should help...

http://support.sas.com/kb/40/683.html

Cynthia_sas
SAS Super FREQ

Hi:

In the simplest method, you override &_ODSDEST before the invocation of %STPBEGIN, like this:

*ProcessBody;

%let _odsdest=rtf;

%stpbegin;

proc print data=work.test;

run;

%stpend;

   

*ProcessBody;

%let _odsdest=msoffice2k;

%stpbegin;

proc print data=work.test;

run;

%stpend;

  

*ProcessBody;

%let _odsdest=csvall;

%stpbegin;

proc print data=work.test;

run;

%stpend;

*ProcessBody;

%let _odsdest=pdf;

%stpbegin;

proc print data=work.test;

run;

%stpend;

   

This override method is for you, as the stored process developer to take control of the ODS destination. However, the pitfall of this approach is that not every client application can "receive" all types of output. For example, using the SAS Add-in for Microsoft Office, and Excel, Excel can "receive" HTML results, SASReport XML results and CSV results. PowerPoint, on the other hand, can only "receive" SASReport XML results. Word can "receive" HTML and RTF results. Excel cannot, for example "receive" PDF results, just as PowerPoint cannot "receive"  CSV or HTML results.

However, there is an alternative to using _ODSDEST -- and that alternative gives control to the end user to select the Stored Process result type before they run a stored process or allows them to set a default using the SAS pulldown for options. 

If you are using the STORED PROCESS WEB APPLICATION (SPWA) or using a direct URL to invoke your stored process, then you may need to use the STPSRV_HEADER function to create the correct content-type HTTP header for your output -- but that is a more advanced usage. For most client applications, it is sufficient to override _ODSDEST, once you understand the limitations of what the client apps can "receive" from a stored process.

cynthia

AshleyM
Fluorite | Level 6

Thanks Cynthia. I’ve created a stored process and would like to allow end users the ability to control for output formats before running the stored process. By default, HTML works fine.. I'm just not certain how to give users the option to produce output that opens directly in SPSS or Excel, or as a PDF.

Cynthia_sas
SAS Super FREQ

Hi:

  If you are going to allow your users to select a destination, then you will have to double check what they select. For example, if the client application is Excel, then you can't let them select PDF. If they are in EG or the Stored Process Web App then you can let them select PDF. If they are in Web Report Studio, then no matter WHAT they select, the WRS interface will change ANYTHING they select to SASReport XML, same thing for PowerPoint.

  So, it is not as easy as it sounds. The only client apps that will accept or receive PDF output are EG, the Information Delivery Portal or the Stored Process Web App. If you are going to use any client other than EG, you will have to send an STPSRV_HEADER. If you are using EG or your users will be submitting the stored process from EG, then you can, I think use the simple %STPBEGIN override method.

  At this point, you might want to go over to the Stored Process forum discussion and look for references to the Information Delivery Portal, PDF and/or STPSRV_HEADER. You might also want to look at the Stored Process Developer's guide or some of the Tech Support notes on the subject about returning results other than the default to the various client applications.

cynthia

Cynthia_sas
SAS Super FREQ

Astounding:

  For a stored process, all the macro variables that will come from the prompting framework should be declared in a %GLOBAL statement. So, Ashley's "internal" and local macro variables will not need to be in a
%GLOBAL statement, but the macro variables that will come from stored process PROMPTS should be declared.

Ashley:

Anytime you have a macro compile error, such as this one (from one of your earlier posts):

ERROR: There is no matching %IF statement for the %ELSE. A dummy macro will be compiled.

You have to fix that first. I think that part of what's wrong with the code you originally posted is a misplaced
%LET statement

15        +%if %length(&DISTRICT) >= 0 %then %do;

16        +

17        +%if %length(&where_clause) > 0 %then %let where_clause = &where_clause and;

18        +

19        +%let where_clause = &where_clause (DISTRICT = "&DISTRICT");

ERROR: There is no matching %IF statement for the %ELSE. A dummy macro will be compiled.

20        +

21        +

22        +%else %let where_clause = &where_clause and;

23        +

24        +%let where_clause = &where_clause;

25        +

26        +

27        +%end;

where you have %let where_clause ... between the %IF and the %ELSE

In fact, I can replicate this error message by doing something similar in a test:

** problem with %let statement between the %if and the %else;

%macro testwrong();

%if %length(&test) > 0 %then %do;

  %if &test = y %then %put this is if 1;

  %let macvar=xxx;

  %else %if &test2 = y %then %put this is else if 1;

%end;

%mend testwrong;

   

options mprint mlogic symbolgen;

%let test=y;

%let test2=;

%testwrong()

which results in the same error message in the SAS log. The logic of where the %LET statement doesn't make sense to me, anyway, but I usually always code my %IF and %ELSE with %DO/%END, to make it very, very clear what is being executed and under what condition.

My "wrong" code shows the same message in the SAS log:

382  ** problem with %let statement between the %if and the %else;

383  %macro testwrong();

384  %if %length(&test) > 0 %then %do;

385    %if &test = y %then %put this is if 1;

386    %let macvar=xxx;

387    %else %if &test2 = y %then %put this is else if 1;

ERROR: There is no matching %IF statement for the %ELSE.

ERROR: A dummy macro will be compiled.

388  %end;

389  %mend testwrong;

390

391  options mprint mlogic symbolgen;

392  %let test=y;

393  %let test2=;

394  %testwrong()

     -

     180

WARNING: Apparent invocation of macro TESTWRONG not resolved.

ERROR 180-322: Statement is not valid or it is used out of proper order.

So, until you fix any macro compile errors, you will not be generating anything useful with your macro invocation and you can't trust what happens when you execute the macro. In fact, with the "a dummy macro will be compiled message" that should be your indicator that your macro code is "broken". That's why I suggested that you step back and try just 1 %IF statement and build 1 correct WHERE Statement before you jumped into building multiple or additive WHERE statements. Only syntactically correct macro code is compiled and until your macro program compiles successfully, there's not going to be anything to "call" when you invoke the macro by name.

Several version of the above macro program (with the %LET inside a %IF/%DO) would be these. Since I don't know where your %LET should logically go, I just created 2 different versions. Both of these macro programs compile correctly. Of course, the results for MACVAR would be logically different for both of these invocations.

** coded %IF statement using %do/%end;
%macro testright();
%if %length(&test) > 0 %then %do;
  %if &test = y %then %do;
      %put this is if 1;
      %let macvar=xxx;
      %put macvar is &macvar;
  %end;
  %else %if &test2 = y %then %do;
        %put this is else if 1;
  %end;
%end;
%mend testright;

  

options mprint mlogic symbolgen;
%let test=y;
%let test2=;
%testright()


%macro testalt();
%if %length(&test) > 0 %then %do;
  %let macvar=xxx;
  %put macvar is &macvar;
  %if &test = y %then %do;
      %put this is if 1;
  %end;
  %else %if &test2 = y %then %do;
      %put this is else if 1;
  %end;
%end;
%mend testalt;

options mprint mlogic symbolgen;
%let test=y;
%let test2=;
%testalt()

I still think you need to take a step back and understand how macro programs and macro %IF statements work and define the code that you expect to generate. You seem to want to generate "additive" WHERE statements joined by the AND operator. This is only ONE way to generate WHERE statements. The WHERE ALSO is another way to augment or modify a WHERE statement condition. For example, try this:

ods listing;

proc print data=sashelp.class;

  where sex = 'F';

  where also age gt 14;

run;

The type of code you need to generate might be easier to do in a macro program if you considered using WHERE ALSO because then you could create WHOLE statements in discrete %IF/%DO/%END sections.

cynthia

Astounding
PROC Star

Cynthia,

You're right about some of the variables needing to be %GLOBAL.  I was questioning those that have a &_COUNT matching variable, and could have been more specific when I mentioned that.  In this particular application:

When &DISTRICT_COUNT > 0, &DISTRICT will exist.  There will be no problem.

When &DISTRICT_COUNT=0, &DISTRICT will not exist.  However, the internal code will not attempt to use &DISTRICT in that case. 

This would be a test that I would run, if I had SAS access at the moment.  Having failed to define &DISTRICT at all:

%macro test;

%if 5=4 %then %put &DISTRICT;

%mend test;

%test

Would that generate an error (or any message at all, for that matter)?

Having to rush out, I want to give your post a more careful read later.  Very good point about WHERE ALSO.

art297
Opal | Level 21

Astounding: No, it wouldn't cause an error.  However, if the condition were 5=5, or any other true statement, yes it would cause an error.

However, as Cynthia mentioned, it wouldn't cause an error in either case if &district had been defined as a global macro variable.

Cynthia_sas
SAS Super FREQ

Hi Astounding:

  Yes, many coding techniques WILL work. That was not my point. I pasted the entire list of user defined macro variables from the EG posted code and put them in a %GLOBAL statement -- since the OP never said which macro variables came from prompts, I erred on the side of pasting everything.

  It was not for me to guess which macro variables were coming from prompts or not. I am not trying to argue with you or quibble over one variable versus another. If DISTRICT_COUNT is coming from a prompt, then it should be declared in a %GLOBAL statement. If DISTRICT_COUNT is a macro variable created by the stored process server, then it doesn't need to be declared, but it won't hurt if it is declared. My original statement is based on the doc, which we used as the foundation for our stored process class:

"The %GLOBAL declarations create an empty macro variable for each possible input parameter and enable you to reference the macro variable in the stored process even if it was not set by the stored process client. If you do not declare input parameters in a %GLOBAL statement, then any references to an unset input parameter will result in WARNING messages in the SAS log."

(page 10 of the Stored Process Developer's Guide(underlining mine)

http://support.sas.com/documentation/cdl/en/stpug/62758/PDF/default/stpug.pdf)

%GLOBAL will not hurt DISTRICT_COUNT, which, if it is coming from the server will be global in scope, anyway. An "unset" input parameter would be a prompt for which the user did not make a choice. One way to force the user to make a choice in the prompting framework (in order to make coding easier -- so you always guarantee that there is a value) is to mark the prompt as REQUIRED when you define the prompt. Or, you can give the user a "none" choice or make "none" the default for a parameter.

  This is another reason why I recommended getting the macro working first to generate the WHERE statements that are needed. Because using a macro program in a stored process does add another level of complexity to debugging.

  

cynthia

NN
Quartz | Level 8 NN
Quartz | Level 8

Hi,

Sorry i hadnt Checked or tested my code...

My main intention was to direct you as to how you could put in conditions for Parameters where you have SELECT MULTIPLE VALUES.

As ART suggested there are a few Dots which appear in my code you would have to remove these additionally there is "%put a " remove this too..

82        +%put a

And yes the _n_ in where will not work in where :smileysilly:

... Astounding has given the right solution.. The objective was to have 1 fixed condition in where and the rest to be followed with AND

AshleyM
Fluorite | Level 6

For those of you that are curious as to what the correct answer was I'm including it here. Thank you again for everyone who participated in this community effort! Smiley Happy

libname IDB "/res/IDB/updates";

run;

Options mprint;

%macro data();

data work.test;

set idb.cv00on;

where (tapeyear ne 0)

%if &CIRCUIT_COUNT >= 0 %then %do;

    AND CIRCUIT IN

        (

            %DO I = 1 %TO &CIRCUIT_COUNT;

                %if &i=1 %then %do;

               &CIRCUIT

                %end;

                %else %do;

                &&CIRCUIT&I

                %end;

             %END;

        )

%END;

%if &DISTRICT_COUNT > 0 %then %do;

    AND trim(left(DISTRICT)) IN

        (

            %DO I = 1 %TO &DISTRICT_COUNT;

                %if &i=1 %then %do;

                "%trim(%left(&DISTRICT))"

                %end;

                %else %do;

                "%trim(%left(&&DISTRICT&I))"

                %end;

             %END;

        )

%END;

%if %length(&DOCKET) > 0 %then %do;

    and DOCKET = "&DOCKET"

%end;

%if %length(&FILEDATE_min) > 0 %then %do;

and FILEDATE between "&filedate_min"d and "&filedate_max"d

%end;

%if %length(&termDATE_min) > 0 %then %do;

and TERMDATE between "&termdate_min"d and "&termdate_max"d

%end;

%if &NOS_COUNT > 0 %then %do;

    AND NOS IN

        (

            %DO I = 1 %TO &NOS_COUNT;

                %if &i=1 %then %do;

               &nos

                %end;

                %else %do;

                &&nos&i

                %end;

             %END;

        )

%END;

%if &DISP_COUNT > 0 %then %do;

    AND DISP IN

        (

            %DO I = 1 %TO &DISP_COUNT;

                %if &i=1 %then %do;

               &disp

                %end;

                %else %do;

                &&disp&i

                %end;

             %END;

        )

%END;

;

run;

%mend;

%data

*ProcessBody;

%stpbegin;

proc print data=work.test;

run;

%stpend;

Astounding
PROC Star

Ashley,

One last step that I would highly recommend ...

Insert right after the %macro statement:

%local i;

This time it took a village!

sas-innovate-2024.png

Don't miss out on SAS Innovate - Register now for the FREE Livestream!

Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.

 

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
  • 44 replies
  • 3056 views
  • 1 like
  • 7 in conversation