I am building macro whitch generates empty table by my own structure from other table. How to change variable type?
example from my code:
`%let vname = %sysfunc(getvarc(&dsid,%sysfunc(varnum(&dsid,varName))));
%let vtype = %sysfunc(getvarc(&dsid,%sysfunc(varnum(&dsid,varType))));
%let vformat = %sysfunc(getvarc(&dsid,%sysfunc(varnum(&dsid,varFormat))));
%if &vtype = C %then %do;
&vname=putc(&vname,&vformat);
%end;`
And it's not working... Any other ideas how to change var type?
You should be clear whether you just need empty table with some columns in a changed data type (definition) or you'd also like to actually convert the data content/values. First case should be much easier.
Because currently in
&vname=putc(&vname,&vformat);
you're trying to convert the data values, not the definition. The definition of variable is not changed and in data step actually can't be changed.
You can't create a "new" variable when there's still the original variable present inside your data step with same name.
In data step, you'd need to define new variables with different names inside data step and use RENAME (new to to original names) and DROP (original names) options on output dataset to end up with same name in output dataset (I can clarify if needed).
For just defining the empty table, PROC SQL could be easier, you need to create a code like:
proc sql;
create table lib.table (
orig_var1 type format informat label
, orig_var2 NEWTYPE format informat label
, ...
);
quit;
which can be built from dictionary.columns. This is also easier to keep original order of variables (not so easy in data step).
You just need to take care to define appropriate length for character variables based on the length of the format used if you'd like to store formatted value of numeric variable in new character variable.
Related
I have internal type A for DF16_RAW and E for DF34_RAW and now at runtime I am creating a dynamic table for that I want datatype DF16_RAW and DF34_RAW with specified precision based on internal type. My code is like below:
CASE WA_COL-INTTYPE.
WHEN 'A'. LO_DESCR_RESULT = CL_ABAP_ELEMDESCR=>GET_DECFLOAT16( ).
WHEN 'E'. LO_DESCR_RESULT = CL_ABAP_ELEMDESCR=>GET_DECFLOAT34( ).
Here I want to get datatype with specified precision. I don't know how it be done?
Some parts of a variable are specific to the ABAP dictionary a.k.a. "DDIC" (search help, output style for the DF* types, etc.) If you want to create one variable with information specific to the ABAP dictionary, then you must refer to an element in the DDIC (i.e. a data element or table/structure component), then use:
lo_descr_result = cl_abap_typedescr=>describe_by_name( 'DDICdataelement' ).
or
lo_descr_result = cl_abap_typedescr=>describe_by_name( 'DDICtablestruct-Component' ).
I'm new to SAS and I'm trying to understand a code:
if MAP_ID="+" then output WORK.0201_template;
else
do;
SHEET_ID=MAP_ID;
output WORK.0201_template_f;
end;
What does it mean the MAP_ID="+"? Does it mean that it search on the table for the values where MAP_ID=+, or does it have another menaing?
Thanks
The MAP_ID="+" is a boolean expression that compares the value the variable MAP_ID to the character string literal "+". It will be true when they are the same and false otherwise.
I suspect that the main purpose of this code is to split the data into two different output datasets based on the value of MAP_ID.
It also is changing the value of SHEET_ID. That type of code also looks like something that is designed to carry forward the value of MAP_ID in a retained field SHEET_ID. If I am right then the meaning of the value of + is to keep the same sheet_id. But we would need to seem more of the code and the data to really tell.
Using SAS I'm pulling data from a SQL data base using a pass through for speed as the DB's are quite large. The below code works as expected.
%let expectdate1 = '2013-07-03';*/
proc sql;
connect to ***** as abc (tdpid=***** user='****' password='*****' );
create table Searched_data as
select * from connection to dss(
SELECT *
FROM database.tablename
WHERE CAPTURE_DT >= '2013-07-01' and CAPTURE_DT <= &expectdate1
);
disconnect from abc;
quit;
The issues arises when I wan to have expectate1 parameterised.
so I replace
%let expectdate1 = '2013-07-03';*/
with
%let expectdate1 = put(Date(),YYMMDD10.);
This doesnt work and the error Im getting is something like
....WHERE CAPTURE_DT >= '2013-07-01' and CAPTURE_DT <= put(Date(),YYMMDD10) .....
So its not evaluating my date code and instead its passing the actual code to SQL and not the resultant string.
Shorack is correct that the PUT statement can not be used with %SYSFUNC, however you can use PUTN successfully.
You should simply need the following.
%LET EXPECTDATE1 = %SYSFUNC(PUTN(%SYSFUNC(DATE()),YYMMDD10.));
%put EXPECTDATE1=&EXPECTDATE1.;
SASLOG:
EXPECTDATE1=2013-08-05
Note: edited for the single quotes you need.
Let me first provide a solution that works, then explain why your approach does not work.
Use this piece of code instead:
data _NULL_;
call symput("expectdate1",cats("'",put(Date(),YYMMDD10.)),"'");
run;
The above piece of code will create your string and then put it into the expectdate1 macro variable.
So, why was your code not working?
That is because you do not make a distinction between SAS functions and SAS macro functions.
put(Date(),YYMMDD10.) are not macro functions (easily distinguished because they start with a percentage sign. -> % <-)
So SAS Macro does not evaluate it and just puts the piece of code into your SQL statement, literally.
Now there is something called the %sysfunc function. It is a macro function that will perform the enclosed normal function.
So %sysfunc(Date()) would be resolved by SAS macro before setting the macro variable expectdate.
Note that each function needs to be enclosed by the %sysfunc function, i.e.,
%let someVariable = %sysfunc(mean(max(1,3),5)); /*WRONG*/
%let someVariable = %sysfunc(mean(%sysfunc(max(1,3)),5)); /*RIGHT*/
That being said, it does not work for some SAS functions and put is one of them. That is why i provided the solution on top: use a data step to prepare it any way you like and write the result into a macro variable.
I am trying to add a new record to my internal table and this code is giving me an error, but I am doing exactly the same thing as in my SAP book. What am I doing wrong?
TYPES : BEGIN OF personel_bilgileri,
Ad TYPE c LENGTH 20,
Soyad TYPE c LENGTH 20,
Telefon_no Type n LENGTH 12,
END OF personel_bilgileri.
TYPES personel_bilgi_tablo_tipi TYPE STANDARD TABLE OF
personel_bilgileri WITH NON-UNIQUE KEY ad soyad.
DATA : personel_bilgi_kaydi TYPE personel_bilgileri,
personel_bilgi_tablosu TYPE personel_bilgi_tablo_tipi.
personel_bilgi_kaydi-ad = 'Murat'.
personel_bilgi_kaydi-soyad = 'Sahin'.
personel_bilgi_kaydi-telefon_no = '5556677'.
APPEND personel_bilgi_kaydi TO personel_bilgileri.
personel_bilgi_kaydi-ad = 'Ayse'.
personel_bilgi_kaydi-soyad = 'Bil'.
personel_bilgi_kaydi-telefon_no = '5556611'.
APPEND personel_bilgi_kaydi TO personel_bilgileri.
personel_bilgi_kaydi-ad = 'Mehmet'.
personel_bilgi_kaydi-soyad = 'Kalan'.
personel_bilgi_kaydi-telefon_no = '5556622'.
APPEND personel_bilgi_kaydi TO personel_bilgileri.
Actually, I don't know which adding record method I should use. I mean there is too many ways to do this operation. Which method will be the true one?
I am getting this error:
The field Personel_bilgileri is unknown, but there are following fields similar names...
Moreover, I can do this with LOOP AT, but I didn't understand the usage of LOOP AT. What does it do?
In your code sample, you first defined PERSONEL_BILGILERI as a TYPE, then PERSONEL_BILGI_TABLO_TIPI as a internal table TYPE of PERSONEL_BILGILERI.
Up to that point, no variables are declared yet. Only data types.
Then:
PERSONEL_BILGI_KAYDI is defined of type PERSONEL_BILGILERI. This is a structure that you use as a work area (which is fine).
PERSONEL_BILGI_TABLOSU is defined of type PERSONEL_BILGI_TABLO_TIPI. So PERSONEL_BILGI_TABLOSU is your internal table.
When you APPEND your work area, you have to append to an internal table, not a data type. try with PERSONEL_BILGI_TABLOSU instead of your type PERSONEL_BILGI:
APPEND personel_bilgi_kaydi TO personel_bilgileri_tablosu.
You need to APPEND your WA(workarea, personel_bilgi_kaydi) in to your table (personel_bilgi_tablosu). You cant append the WA to the defined type.
So it should look like this:
APPEND personel_bilgi_kaydi TO personel_bilgi_tablosu.
Also you can use this code to show them on the page.
LOOP AT personel_bilgi_tablosu into personel_bilgi_kaydi.
write: / 'İSİM: ' ,personel_bilgi_kaydi-ad,
'SOYİSİM: ',personel_bilgi_kaydi-soyad,
'TEL NO: ', personel_bilgi_kaydi-telefon_no.
ENDLOOP.
You can use other methods to show your table on the page, such as REUSE_ALV_GRID_DISPLAY. You can get more information about that in scn.sap.com
Hope it was helpful.
Kolay gelsin.
Talha
I am looking for a way to create a string variable containing certain values of the dataset while going through the data step.
Example data set work.test:
AddToStringYN Value
Y One
Y Two
N Three
Y Four
N Five
So in the end, the variable would look like: OneTwoFour (or even better FourTwoOne).
This looks so simple, but I can't seem to find a way to do it.
I also tried to work with macro variables like this:
%let stringvar=;
Data _null_;
set work.test;
if AddToStringYN = "Y" then do;
call symput('stringvar',"&stringvar" || strip(value));
end;
Run;
But this gives:
GLOBAL STRINGVAR Four
So I only get the last value. I get that this must be because of some misunderstanding of mine about this macro facility, but I don't understand why there is only the last value in the variable.
I thought it was only the last time the symput was called that it was actually executed or something, but then when I adjust the code to:
%let stringvar=;
Data _null_;
set work.test;
if AddToStringYN = "Y" then do;
call symput('stringvar'||strip(value),"&stringvar" || strip(value));
end;
Run;
Then I do get them all:
GLOBAL STRINGVARONE One
GLOBAL STRINGVARTWO Two
GLOBAL STRINGVARFOUR Four
So my last guess is that going through the data step, the 'call symput...' line is actually added to the macro processor where the "&stringvar" is already replaced and only after the final statement are they all executed.
Is this a good assumption or is there another explanation?
And back to the original question: is there an easy way to achieve this (having the desired variable)?
The following is my answer to your identical question on RunSubmit.com. I think you and #Fabio may be over-engineering the solution, it doesn't need any iterating data step code at all...
First, the easy way to do what you're trying to do is like this:
proc sql;
select Value into :StringVar separated by ''
from work.test
where AddToStringYN='Y'
;
quit;
Here, you can take advantage of the SQL interface with SAS/MACRO, using the select into syntax. You could even add an order by clause to get a particular order you're looking for.
Second, since you've happened upon something about the way SAS macro works and you're keen to understand it: in your first example, the first thing the compiler does before executing your code is to resolve the value of &stringvar, which at that point is empty. So after compilation, with this token replaced, your code looks like this to SAS...
%let stringvar=;
Data _null_;
set work.test;
if AddToStringYN = "Y" then do;
call symput('stringvar',"" || strip(value));
end;
Run;
...then SAS goes ahead and runs that code (which happens to be valid code, but is concatenating an empty string to the start of something). And because of the way the data step works, each iteration of the data step is in fact replacing the value of StringVar, which is why at the end of the data step, it's left with the last value that was read in.
Greetings
Seems simple enough, here is my solution:
data a;
set test end=eof;
length cat $100.;
retain cat;
if AddToStringYN = "Y" then do;
cat=trim(left(cat))||trim(left(value));
end;
if eof then do;
call symput("VAR",cat);
output;
end;
run;
%put VAR=&VAR;
in this example you have the concatenation of your variable in the A dataset in the column "CAT" and you have a macrovariable VAR with the same list