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

- 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
- 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
- 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
- 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

How to convert datasets to data steps

How to post code

Maxims of Maximally Efficient SAS Programmers

How to convert datasets to data steps

How to post code

- Mark as New
- Bookmark
- Subscribe
- 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
- 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
- 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
- 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
- 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.