Proc contents in macro VARNUM - sas

I am exporting the SAS contents to excel file and it works good., however the VARNUM option doesnt seem to work and the variables are in alphabetical order in the excel sheet.
here is the loop.
proc sql;
select count(Name) into :NumOfDatasets from Datas;
select Name into :Dataset1-:Dataset%trim(%left(&NumOfDatasets)) from datas;
quit;
%do index = 1 %to &NumOfDatasets;
proc contents data=&ImportLibrary..&&Dataset&index. varnum
out=&ExportLibrary..&&Dataset&index. (keep=name label);run;
proc export data=&ExportLibrary..&&Dataset&index.
outfile="&ExportLocation"
dbms=excelcs replace;
sheet="&&Dataset&index";
run;
%end;

The varnum option on proc contents affects only the report output of the procedure, not the dataset generated with the out= option.
You could just add a proc sort between your contents and export procedures (and move the keep= dataset option from the contents to the export procedure):
proc sql;
select count(Name) into :NumOfDatasets from Datas;
select Name into :Dataset1-:Dataset%trim(%left(&NumOfDatasets)) from datas;
quit;
%do index = 1 %to &NumOfDatasets;
proc contents data=&ImportLibrary..&&Dataset&index.
out=&ExportLibrary..&&Dataset&index.;
run;
proc sort data=&ExportLibrary..&&Dataset&index.;
by varnum;
run;
proc export data=&ExportLibrary..&&Dataset&index.(keep=name label)
outfile="&ExportLocation"
dbms=excelcs
replace;
sheet="&&Dataset&index";
run;
%end;

Related

macro for proc sql select into, good for i=1 but not i=2

I was trying to use proc sql select into to generate macro variables, and I would like to do it for all variables in the code dataset, so I embedded it within a macro. The proc sql runs ok for both cd_1 and cd_2 as there are valid print out. However, only cd_1 has the value I wanted, and cd_2 was not resolved. I have pasted the full code below.
data code;
infile datalines delimiter=',';
input MUSCLE $ STIMULANTSFL $ ;
datalines;
baclofen,amphetamine
carisoprodol,dexmethylphenidate
;
run;
*Selecting all the variables names;
proc sql ;
select name into : vars1 - :vars2 from dictionary.columns
where LIBNAME = 'WORK' and MEMNAME = 'CODE';
quit;
*for all names select the codes;
%macro getcode;
%do i=1 %to 2;
PROC SQL ;
select (trim(&&vars&i.)) into : cd_&i. separated by '|' from code where (trim(&&vars&i.)) ne '';
quit;
%end;
%mend;
%getcode;%put &cd_1;%put &cd_2;
Macro variable scope issue - local versus global.
I suspect your first one only works because you tested it. Move the %PUT to inside the macro to have it resolve. Your macro variables do not exist outside your macro unless you explicitly set them to exist.
Add %GLOBAL to create global macro variables.
data code;
infile datalines delimiter=',';
input MUSCLE $ STIMULANTSFL $;
datalines;
baclofen,amphetamine
carisoprodol,dexmethylphenidate
;
run;
*Selecting all the variables names;
proc sql;
select name into : vars1 - from dictionary.columns where LIBNAME='WORK' and
MEMNAME='CODE';
quit;
option mprint;
*for all names select the codes;
%macro getcode;
%do i=1 %to 2;
%global cd_&i;
PROC SQL;
select (trim(&&vars&i.)) into : cd_&i. separated by '|' from code
where (trim(&&vars&i.)) ne '';
quit;
%put cd_&i.;
%end;
%mend;
%getcode;
%put &cd_1.;
%put &cd_2.;

Proc Sort Using a Macro

I created 40 plus tables (using a marco, which I just learned how to do) that I would like to apply the Proc Sort statement to. I want each table sorted by the same variable 'Account_Description' (each table contains this variable).
The table names are June_53410_v1, June_53420_v1, June_53430_v1, etc. Can I employ a macro, and if so, how can I, to mitigate having to write a proc sort statement for each table?
Thanks!
I found this sample code online but I'm not really sure how it works
%Macro sorter(dsn, var);
proc sort data=&dsn.;
by &var.;
run;
%mend;
%sorter(sample_dataset, age);
Macro that will be used (proc sort write to work):
%Macro sorter(lib,dsn, var);
proc sort data=&lib..&dsn. out=&dsn.;
by &var.;
run;
%mend;
Get dictionary of tables that contains in name some chars (its maby “June_” instead “AIR”) :
data sashelp_tables;
set sashelp.vtable;
where LIBNAME="SASHELP" and MEMNAME contains "AIR"
;
run;
Write code to string , and execute it for all tables:
data _NULL_;
length code $ 200;
set sashelp_tables;
code=cat('%sorter(',LIBNAME,',',MEMNAME,',AIR);');
call execute(code);
run;
I appreciate everyone's input-I think I found an answer though using this code:
%macro st (ds);
proc sort data = &ds;
by Account_Description;
run;
%mend;
%st(June_53410_v1);
%st(June_53420_v1);
You can use this solution, where lib is libname, mask_table is mask to table(June_ in your task) and var is variable to sort tables:
%macro sorter(lib,mask_table, var); %macro d;%mend d;
%let table_list = 0;
proc sql noprint;
select strip(libname) || '.' || strip(memname),count(memname)
into: table_list separated by ' '
from dictionary.tables
where libname = UPCASE("&lib.") and memname LIKE UPCASE("&mask_table.")||"%";
quit;
%do i=1 %to %sysfunc(countw(&table_list,%str( )));
%let name&i = %scan(&table_list, &i, %str( ));
proc sort data=&&name&i.;
by &var.;
run;
%end;
%mend sorter;
%sorter(WORK,June,Account_Description);

Using Proc sql to get statiscs for many variables

I want to use Porc sql to create a data set that contains some statistics as min and max for a lots of variables. The code below only returns a data set with min and max for first variable, for the rest of variables min and max are not show in the data set.
proc sql;
CREATE TABLE Lib.VarNum AS
%do i=1 %to &nvars;
select min(%SCAN(&numvar,&i)) as Min%SCAN(&numvar,&i),
max(%SCAN(&numvar,&i)) as Max%SCAN(&numvar,&i)
from &data (keep= _numeric_);
%end;
quit;
Somebody can help me?
using proc means is best way to do this.
proc means data=sashelp.cars noprint;
var _numeric_;
output out=want (drop= _type_ _freq_ )min(_numeric_) =
max(_numeric_) =/autoname;
run;
but if you want to so it by Proc SQL easiest to macrovariables from dictionary.columns and use them in your tables.
/* creating macrovariables using dictionary.columns*/
proc sql noprint;
select 'min('|| trim(name)||') as min_'||name,
'max('|| trim(name)||') as max_'||name
into :min separated by ',' , :max separated by ','
from dictionary.columns
where libname ='SASHELP'
and memname ='CARS'
and upcase(type) ='NUM';
Values of macrovariable can be checkedly and only partially shown
%put &min;
min(MSRP) as min_MSRP,min(Invoice) as min_Invoice,min(EngineSize) as min_EngineSize
use this macro variables in proc sql statement as shown below.
proc sql;
create table want as
select &min, &max from sashelp.cars;

How do you read multiple specific datasets and append to one big dataset?

How do you read multiple specific datasets and append to one big dataset?
For example I within a library I have 100s of datasets but I only want to append the datasets that have _du1, _du2
The format and column names are the same
My stab of it doesnt work:
PROC SQL NOPRINT;
SELECT memname INTO :tab1-:tab103 FROM sashelp.vtable
where memname like '_DU%';
SELECT count(*) INTO :obs FROM sashelp.vtable
where memname like '_DU%';
QUIT;
%macro rubber;
%do i=1 %to i=&obs;
proc append base=tot_comb data=&&tab&i force;
run;
%end;
%mend;
%rubber;
PROC APPEND may not actually be faster in this case, or at least not faster by enough to justify doing it, than just writing a datastep.
data tot_comb;
set work._DU:; *or your libname;
run;
This will work if you are on SAS 9.2 or later. If you're on 9.1 or earlier, you'll need to do one proc sql step, like
proc sql;
select memname into :namelist separated by ' '
from dictionary.columns
where libname='WORK' /* or your libname */
and memname eqt '_DU';
quit;
*eqt is like starts with;
data tot_comb;
set &namelist;
run;
That only requires one pass to write, and I'm not sure it will be much slower than so many calls to PROC APPEND.
Here is some code that will get you all the data set names from a given library with some characteristics (starts with _DU). You could use the final macro in a variety of ways to append data sets.
Data _DU1;
var="One";
Run;
Data _DU2;
var="Two";
Run;
PROC SQL;
create table main as
SELECT *
FROM DICTIONARY.COLUMNS
WHERE UPCASE(LIBNAME)="WORK" AND
UPCASE(MEMNAME) like '_DU%';
Select memname
into :dsn separated by ' '
from main;
QUIT;
%Put &dsn;
EDIT (according to your comment)
I added some UPCASE statements and used your count macro var for the number of tab macros
Narrowing your where statement should make your code more efficient
Try this (some of the code is untested):
PROC SQL NOPRINT;
SELECT count(*)
INTO :obs
FROM sashelp.vtable
where UPCASE(LIBNAME)="<YOUR LIB IN UPCASE>" AND
upcase(memname) like '_DU%';
%Let obs=&obs;
SELECT memname
INTO :tab1-:tab&obs
FROM sashelp.vtable
where UPCASE(LIBNAME)="<YOUR LIB IN UPCASE>" AND
upcase(memname) like '_DU%';
QUIT;
%macro rubber;
%do i=1 %to &obs;
proc append base=tot_comb data=&&tab&i force; run;
%end;
%mend;
%rubber;

How can I assign a value to a column as I'm using PROC EXPORT?

%if %sysfunc(exist(working.__extra_nos__)) %then %do;
proc export data=working.__extra_nos__
dbms=oracle replace;
password="&password.";
tablename="sch.no_selection_&env_type.";
url="&dburl.";
username="&user.";
run;
sch.no_selection_&env_type also has column called identifier, which isn't in __extra_nos__ so I want to set it to &identifier as I export it.
How can I do this?
It's a lot easier to access database DBMSs by LIBNAME rather than PROC EXPORT.
http://support.sas.com/documentation/cdl/en/acreldb/63647/HTML/default/viewer.htm#a003113591.htm
libname mydblib oracle user=testuser password=testpass path=hrdept_002;
[adjust for your oracle installation details]
Then instead of export, you just create or modify a table using normal language (SQL or Data Step)...
proc sql;
create table mydblib.sch.no_selection_&env_type. as
select *, "&identifier" as identifier from work.tempextras;
quit;
or
data mydblib.sch.no_selection_&env_type.;
set work.tempextras;
identifier="&identifier";
run;
Create a dataset from your __extra_nos__ and put the identifier in then. Then export that dataset.
data work.tempextras;
set working.__extra_nos__;
identifier = &identifier.;
run;
%if %sysfunc(exist(working.__extra_nos__)) %then %do;
proc export data=work.tempextras;
dbms=oracle replace;
password="&password.";
tablename="sch.no_selection_&env_type.";
url="&dburl.";
username="&user.";
run;
proc datasets library = work; /*delete the temp dataset*/
delete tempextras;
run;