%let vc = 12025;
ideal output (with format comma ) is 12,025;
but %put %sysfunc(put(&vc,comma6.)) seems not working. Error as below.
ERROR: The PUT function referenced in the %SYSFUNC or %QSYSFUNC macro function is not found.
The PUT function is not available with %SYSFUNC, however you can use PUTN for numeric values, or PUTC for character.
Try :
%put %sysfunc(putn(&vc,comma6.));
An alternative to using the putn() function to format values returned by %sysfunc() is to use the little known 2nd parameter of %sysfunc() like so:
%let vc = 12025;
%put %sysfunc(sum(&vc),comma6.);
The second argument applies a format to the result returned by whatever function %sysfunc() is calling. In the above example, I'm just summing a number by itself which effectively just returns the number. If it was a character value, I could use the cats() function.
Worth noting as it will simplify code if you want to do something like:
%put %sysfunc(putn(%sysfunc(date()),date9.));
as it becomes:
%put %sysfunc(date(),date9.);
Related
I would like to write a PROC FORMAT to check for errors in a variable that serves as a unique identifier. The variable is a character string of length 16, and it usually has a number of trailing zeros, like so:
0000001234567890
I would like the PROC to output an error to the log if, for example, the variable is null or if the length of the sting is different from 16. Can this be done in the same proc, without having to go through functions such as length()?
what I would like to obtain is something like:
proc format;
value $ id_error
' ' = _ERROR_
*length ne 16 = _ERROR_;
*other errors* = _ERROR_;
other = 'OK';
run;
Is something equivalent to the above possible to do with a single proc format?
Reeza's suggestion to use PROC FCMP is along the right path I think. You can't really check for length in a format without it.
This is covered in the documentation here. The basic structure is, write a fcmp function that takes a character value as input (for a character format) and returns a character value, and then call that fcmp function with no arguments in the format; the input value for the format will be provided automatically.
In 9.3+:
data have;
length cardno $32;
input cardno;
datalines;
1234567890123456
0000153456789152
0000000000000000
1111111111111111
9999999999999999
0123456
01234567897456
0123154654564897987445
;;;;
run;
proc fcmp outlib=work.funcs.fmts;
function check16fmt(charval $) $;
length retval $16;
if length(charval) = 16 then retval='VALID VALUE';
else retval='_ERROR_';
return(retval);
endsub;
run;
options cmplib=work.funcs;
proc format;
value $chk16f
low-high = [check16fmt()];
quit;
data want;
set have;
format cardno $chk16f.;
run;
I'm creating a function that displays a lot of variables with the format Variable + Variable Name.
Define LibPub out(list)=
Func
Local X
for x,1,dim(list)
list[x]->name // How can I get the variable name here?
Disp name+list[x]
EndFor
Return 1
EndFunc
Given a list value, there is no way to find its name.
Consider this example:
a:={1,2,3,4}
b:=a ; this stores {1,2,3,4} in b
out(b)
Line 1: First the value {1,2,3,4} is created. Then an variable with name a is created and its value is set to {1,2,3,4}.
Line 2: The expression a is evaluated; the result is {1,2,3,4}. A new variable with the name b is created and its value is set to `{1,2,3,4}.
Line 3: The expression b is evaluated. The variable reference looks up what value is stored in b. The result is {1,2,3,4}. This value is then passed to the function out.
The function out receives the value {1,2,3,4}. Given the value, there is no way of knowing whether the value happened to be stored in a variable. Here the value is stored in both a and b.
However we can also look at out({1,1,1,1}+{0,2,3,4}).
The system will evaluate {1,1,1,1}+{0,2,3,4} and get {1,2,3,4}. Then out is called. The value out received the result of an expression, but an equivalent value happens to be stored in a and b. This means that the values doesn't have a name.
In general: Variables have a name and a value. Values don't have names.
If you need to print a name, then look into strings.
This will be memory intensive, but you could keep a string of variable names, and separate each name by some number of characters and get a substring based on the index of the variable in the list that you want to get. For instance, say you want to access index zero, then you take a substring starting at (index of variable * length of variable name, indexofvariable *length + length+1).
The string will be like this: say you had the variables foo, bas, random, impetus
the string will be stored like so: "foo bas random impetus "
I need to create SAS informat that will change all case versions of 'Male' and 'Female' to digits.
I found in the documentation that there is UPCASE options that does the job. "converts all raw data values to uppercase before they are compared to the possible ranges. If you use UPCASE, then make sure the values or ranges you specify are in uppercase"
Unfortunately after adding the UPCASE option none of the input values is read properly.
The SAS version id 9.2.
My code is below.
options fmtsearch=(WORK);
proc format lib=WORK;
invalue gender UPCASE
MALE = 1
FEMALE = 2
;run;
data _null_;
q='MALE';
x=input(q,gender.);
put q=;
put x=;
run;
The log is:
NOTE: Invalid argument to function INPUT at line 186 column 7.
q=MALE
x=.
q=MALE x=. _ERROR_=1 _N_=1
What is the proper usage of this option?
Very simple, just put UPCASE inside brackets...
I'm calling a procedure in a script and passing variables like this:
##./procedudure.sql 'var1' 'var2' 'var3'
In the procedure I'm using the values like this:
DEFINE variable1 = '&1'
DEFINE variable2 = '&2'
DEFINE variable3 = '&3'
...
insert into TABLE (id, text) values ('&varibale1', '&variable2&variable3')
I want to be able to call the procedure with only two parameters instead of 3 so that the last one is replaced with empty string. But when I call it like this, I get this prompt:
Enter value for 3:
I've also tried to use the parameters like this, but with the same result:
DEFINE variable2 = '&2' || '&3'
I've found this page for using prompt for missing variable, but couldn't find anywhere how to set a default value: https://blogs.oracle.com/opal/entry/sqlplus_101_substitution_varia#9_14
As you can see from the code, I want the last parameters to be concatenated. This should be a workaround for 240-character limit.
Well yes I see it's old but... until now, unanswered!
OP, this is what you're looking for but it's not exactly simple!
I originally spotted the technique on Tanel Poder's website but not sure if he came up with it or not.
Anyway, here I'm using it to setup defaults in case warning and critical limits are not passed in to the script.
rem setup default values
def DEFAULT_WARN_LEVEL='97'
def DEFAULT_CRIT_LEVEL='99'
rem trick to assign values to &1 and &2 so that SQL*Plus does not ask
col warn_level new_value 1
col crit_level new_value 2
select null warn_level
, null crit_level
from dual
where 1=2
/
rem if values were passed in, use them, if not, use the defaults
select nvl('&1','&DEFAULT_WARN_LEVEL') warn_level
, nvl('&2','&DEFAULT_CRIT_LEVEL') crit_level
from dual
/
rem the values, either passed in or defaults are now in &1 and &2
rem put the values in meaningful variables
def warn_level='&1'
def crit_level='&2'
When you code it as DEFINE variable3 = '&3' in your procedure, the system thinks 3 is variable and it will always prompt for its value.
In case you want to pass a default value for 3, you should do DEFINE 3 = YOUR_VALUE_FOR_PARAM_3
In the example link, section 9.14, I don't see where he uses any default value. He just either asks for it, or takes the parameter. SQLPLUS always is going to ask for any &1, &2, .. he sees in your file, if it is not given as input parameter. No matter how and where you use it. It's not like in Bash, where he just replaces $1 with null, and doesn't do anything. I don't think you can disable the auto-asking in SQLPLUS.
I am using ireport 3.7.1. I have made a connection with my database.I have a procedure which when given an input in number ,it returns the word format of the number i.e if I give input 10,it will return ten. The problem is when I am executing the procedure in pl/sql developer,I am getting the proper output but when I am firing the same procedure in ireport it's giving me this exception
Cannot cast object '(10)' with class 'java.lang.String' to class 'java.lang.Integer' .
Casting straight from a String to an Integer is not possible. You'll want to use the function Integer.parseInt(stringNumber);
(10) isn't a properly formated integer. Not even for PL/SQL:
select '(10)' +0 from dual;
> ORA-01722: invalid number
I could only suggest you to trace back the point where those ( ) come from. And fix your code at that position instead. Just a wild guess, some number formats use parenthesis to represent negative numbers. Maybe this is your case?
That being said, if you still want to locally remove the parenthesis that have somehow lurked inside of your string:
String str = "(10)";
int value = Integer.parseInt(str.substring(1, str.length()-1));
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// *blindly* get away of first and last character
// assuming those are `(` and `)`
For something a little bit more robust, and assuming parenthesis denotes negative numbers, you should try some regex:
String str = "(10)";
str = str.replaceFirst("\\(([0-9]+)\\)", "-$1");
// ^^^ ^^^ ^
// replace integer between parenthesis by its negative value
// i.e.: "(10)" become "-10" (as a *string*)
int value = Integer.parseInt(str);