turn on suggestions

Auto-suggest helps you quickly narrow down your search results by suggesting possible matches as you type.

Showing results for

Find a Community

- Home
- /
- SAS Programming
- /
- Base SAS Programming
- /
- Dynamic apply format by making the fmtname from a ...

Topic Options

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

02-23-2017 06:22 AM - edited 02-23-2017 06:33 AM

Hello

I am using SAS9.4 on a Windows10 PC environment.

I am trying to create a string column to contain a full description by using a format within a PUT statement. I want the format name to be generated dynamically based on a value in a different column. This seems feasible but I can't quite nail it, example program attached.

I have this problem on a couple of programs so all help will be gratefully received, thank you.

Accepted Solutions

Solution

02-24-2017
05:43 AM

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to mkeintz

02-23-2017 04:08 PM

```
/* T1002580 Using putc or putn with format names in your data
Using putc or putn with format names in your data
This seems to work
inspired by
https://goo.gl/ktxY1O
https://communities.sas.com/t5/Base-SAS-Programming/Dynamic-apply-format-by-making-the-fmtname-from-a-value-in-the/m-p/335244
HAVE
====
proc format;
value $ FMTA1X
"A" = "this was discount $10"
"B" = "this was discount $20"
;
value $ FMTA2X
"A" = "this was discount $300"
"B" = "this was discount $400"
;
run;
Up to 40 obs WORK.HAVE total obs=5
Obs PRODTYPE DISCOUNT
1 A1 B
2 A2 A
3 A2 A
4 A2 B
5 A1 B
WANT
====
Up to 40 obs WORK.DEMO_DESCRIPTION_HARDCODE total obs=5
Obs PRODTYPE DISCOUNT DISCOUNT_DESC
1 A1 B this was discount $20 putc(discount,$fmta1x.)
2 A2 A this was discount $300
3 A2 A this was discount $300
4 A2 B this was discount $400
5 A1 B this was discount $20
SOLUTION
========
data have;
input Prodtype $ Discount $;
cards4;
A1 B
A2 A
A2 A
A2 B
A1 B
;;;;
run;quit;
data want;
retain prodtype discount discount_desc;
length discount_desc $44;
set have;
fmt=cats('$fmt',prodtype,'x');
Discount_desc = putc(Discount,fmt);
run;quit;
Up to 40 obs WORK.WANT total obs=5
Obs PRODTYPE DISCOUNT DISCOUNT_DESC FMT
1 A1 B this was discount $20 $fmtA1x
2 A2 A this was discount $300 $fmtA2x
3 A2 A this was discount $300 $fmtA2x
4 A2 B this was discount $400 $fmtA2x
5 A1 B this was discount $20 $fmtA1x
```

All Replies

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to RB1Kenobi

02-23-2017 06:42 AM

Not possible.

The format is set when the data step is compiled, so formats need to be named literally.

From the documentation of the put() function:

*format*.

contains the SAS format that you want applied to the value that is specified in the source. This argument must be the name of a format with a period and optional width and decimal specifications, **not a character constant, variable, or expression**.

(Emphasis by me)

Read the documentation.

---------------------------------------------------------------------------------------------

Maxims of Maximally Efficient SAS Programmers

Maxims of Maximally Efficient SAS Programmers

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to RB1Kenobi

02-23-2017 06:44 AM

Post your examples as text in a code window ({i} above post). Is there a reason you want to try to automate it, you will need to have the list somewhere if so. If its just a couple then what you have is fine. To automate will take more code:

data fmts; length fmt_cond fmt $200; input fmt_cond $ fmt $; datalines; A1 $fmt2 A2 $fmt1 ; run; data _null_; set fmts end=last; if _n_=1 then call execute('data want; set have;'); call execute('if variable="'||strip(fmt_cond)||'" then res=put( ...); if last then call execute('run;'); run;

Just as an example, however I would really question why this is necessary at all.

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to RB1Kenobi

02-23-2017 09:02 AM - edited 02-23-2017 09:15 AM

PUTC/PUTN allow format names that are from a variable.

Borrowing code:

data fmts;

length fmt_cond fmt $200;

input fmt_cond $ fmt $;

datalines;

A1 $fmt2

A2 $fmt1

;

run;

Data want;

set fmts;

want_var = putc(fmt_cond, fmt);

Run;

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to RB1Kenobi

02-23-2017 10:12 AM

I suspect you would also be well served by a hash lookup table, keyed on 2 vars: PRODTYPE and DISCOUNT. Make a lookup dataset, with all the expected combinations of prodtype,discount, and discount_desc. Then load it into a hash object to use in the data step:

```
data lookup;
input prodtype :$2. discount :$1. @6 discount_desc $30.;
datalines;
A1 A this was discount $10
A1 B this was discount $20
A2 A this was discount $300
A2 B this was discount $400
run;
data demo_description_dynamic (drop=rc);
set demodata;
if _n_=1 then do;
if 0 then set lookup;
declare hash h (dataset:'lookup');
h.definekey('prodtype','discount');
h.definedata(all:'Y');
h.definedone();
end;
rc=h.find();
if rc^=0 then call missing(discount_desc);
run;
```

When the h.find() method is successful, two things happen: RC=0 and discount_desc is retrieved from the desired item in hash object h. If it's unsuccessful, RC ^=0 and * discount_desc is unchanged from the last successful h.find()*. That's why you see discount_desc set to missing when rc^=0.

Solution

02-24-2017
05:43 AM

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to mkeintz

02-23-2017 04:08 PM

```
/* T1002580 Using putc or putn with format names in your data
Using putc or putn with format names in your data
This seems to work
inspired by
https://goo.gl/ktxY1O
https://communities.sas.com/t5/Base-SAS-Programming/Dynamic-apply-format-by-making-the-fmtname-from-a-value-in-the/m-p/335244
HAVE
====
proc format;
value $ FMTA1X
"A" = "this was discount $10"
"B" = "this was discount $20"
;
value $ FMTA2X
"A" = "this was discount $300"
"B" = "this was discount $400"
;
run;
Up to 40 obs WORK.HAVE total obs=5
Obs PRODTYPE DISCOUNT
1 A1 B
2 A2 A
3 A2 A
4 A2 B
5 A1 B
WANT
====
Up to 40 obs WORK.DEMO_DESCRIPTION_HARDCODE total obs=5
Obs PRODTYPE DISCOUNT DISCOUNT_DESC
1 A1 B this was discount $20 putc(discount,$fmta1x.)
2 A2 A this was discount $300
3 A2 A this was discount $300
4 A2 B this was discount $400
5 A1 B this was discount $20
SOLUTION
========
data have;
input Prodtype $ Discount $;
cards4;
A1 B
A2 A
A2 A
A2 B
A1 B
;;;;
run;quit;
data want;
retain prodtype discount discount_desc;
length discount_desc $44;
set have;
fmt=cats('$fmt',prodtype,'x');
Discount_desc = putc(Discount,fmt);
run;quit;
Up to 40 obs WORK.WANT total obs=5
Obs PRODTYPE DISCOUNT DISCOUNT_DESC FMT
1 A1 B this was discount $20 $fmtA1x
2 A2 A this was discount $300 $fmtA2x
3 A2 A this was discount $300 $fmtA2x
4 A2 B this was discount $400 $fmtA2x
5 A1 B this was discount $20 $fmtA1x
```

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to RB1Kenobi

02-24-2017 05:45 AM

Thank you all for your contributions.

The other way I was looking at the problem was to use create a function (Proc FCMP) which would have been stored in one place and then reference across the different programs.