BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
mhoward2
Obsidian | Level 7

I have the following code. It takes a table that exists, checks for a certain row, duplicates the row, and changes the memo field of the duplicated row. However, the new memo in the duplicated row keeps getting cut off due to the original table's memo length being less than the new memos length. Even though I added a length statement to account for that. What am I doing wrong?

 


DATA WORK.WANT;
LENGTH MEMO $100.;
SET WORK.HAVE;
OUTPUT;

IF MEMO = 'Original Field Value - 36 Characters' AND DATE = '31Jan2025'd AND AMOUNT = 12 THEN DO;
	 MEMO = 'New Field Value - Much Longer Than 36 Characters';
	 AMOUNT =  25;
	OUTPUT;
END;

RUN;

 

Thanks in advance!

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

@mhoward2 wrote:
I have confirmed that my code is correctly duplicating a single row. I start with X rows and end with X+1 and the new row does indeed have the new MEMO value, but it's truncated.

It has a value of "New Field Value - Much Longer Than 3" instead of the full value. I added the format code you suggested and unfortunately no change.

In that case make sure you are actually running the code you showed (share the log) and looking at the dataset it created (and not some other dataset that perhaps has a similar name?).

 

Try just running on that one observations.  You can iterate that test faster.

DATA WANT;
  LENGTH MEMO $100;
  SET HAVE;
  WHERE MEMO = 'Original Field Value - 36 Characters' 
    AND DATE = '31Jan2025'd AND AMOUNT = 12 ;
  put 'BEFORE: ' amount= memo=;
  MEMO = 'New Field Value - Much Longer Than 36 Characters';
  AMOUNT =  25;
  put 'AFTER: ' amount= memo=;
  format memo ;
RUN;

Note that there is no need to include a period in the LENGTH statement as lengths are always integers.

 

View solution in original post

12 REPLIES 12
Tom
Super User Tom
Super User

Did the log show that you wrote at least one more observation to WANT than you read from HAVE?

How did you test if the value of MEMO was truncated?  Did you test if the new value existed, perhaps with a WHERE statement?

proc print data=want;
  where MEMO = 'New Field Value - Much Longer Than 36 Characters';
run;

Or did you just look at the values that were printed?

 

If the latter then did you accidentally attach the $36. display format specification to the variable MEMO in HAVE?  Or perhaps you created HAVE from some external database and it was SAS that mistakenly attached a display format to a character variable?

 

Try adding this statement to your data step.

format memo ;

That will remove any display format attached so that SAS will display the full value when it prints the variable.

mhoward2
Obsidian | Level 7
I have confirmed that my code is correctly duplicating a single row. I start with X rows and end with X+1 and the new row does indeed have the new MEMO value, but it's truncated.

It has a value of "New Field Value - Much Longer Than 3" instead of the full value. I added the format code you suggested and unfortunately no change.
Tom
Super User Tom
Super User

@mhoward2 wrote:
I have confirmed that my code is correctly duplicating a single row. I start with X rows and end with X+1 and the new row does indeed have the new MEMO value, but it's truncated.

It has a value of "New Field Value - Much Longer Than 3" instead of the full value. I added the format code you suggested and unfortunately no change.

In that case make sure you are actually running the code you showed (share the log) and looking at the dataset it created (and not some other dataset that perhaps has a similar name?).

 

Try just running on that one observations.  You can iterate that test faster.

DATA WANT;
  LENGTH MEMO $100;
  SET HAVE;
  WHERE MEMO = 'Original Field Value - 36 Characters' 
    AND DATE = '31Jan2025'd AND AMOUNT = 12 ;
  put 'BEFORE: ' amount= memo=;
  MEMO = 'New Field Value - Much Longer Than 36 Characters';
  AMOUNT =  25;
  put 'AFTER: ' amount= memo=;
  format memo ;
RUN;

Note that there is no need to include a period in the LENGTH statement as lengths are always integers.

 

mhoward2
Obsidian | Level 7
I was fianlly able to figure it out thanks to this and @FreelanceReinh

Thank you so much! I able to move forward with my life.
PaigeMiller
Diamond | Level 26

If the field is truncated in data set HAVE, then nothing you can do will make it appear un-truncated in data set WANT.

 

Did you examine the value in data set HAVE?

--
Paige Miller
mhoward2
Obsidian | Level 7

I apologize if I am not explaining well, and sincerely appreciate the help! In my existing data set, HAVE, the field MEMO has a 36 character format and there are many rows where that field value = "Original Field Value - 36 Characters".

I want to duplicate a single one of those rows (which is working correctly) and then change its MEMO value from the original "Original Field Value - 36 Characters" to "New Field Value - Much Longer Than 36 Characters".

The length statement in the Data Step does change the field to a 100 Character format, but the new value still appears truncated to 36 characters on the output dataset.

PaigeMiller
Diamond | Level 26

@mhoward2 wrote:

I apologize if I am not explaining well, and sincerely appreciate the help! In my existing data set, HAVE, the field MEMO has a 36 character format and there are many rows where that field value = "Original Field Value - 36 Characters".


Format is irrelevant here. What is the length of the field value in data set HAVE?

--
Paige Miller
mhoward2
Obsidian | Level 7
The length of the MEMO field in the HAVE dataset is 36. Which I assume is why my new value is getting truncated at 36 characters. But shouldn't the LENGTH statement in my Data Step allow for longer values?
SASKiwi
PROC Star

What is the length of MEMO in your WANT dataset? Has it increased to 100 or not? If not check your SAS log for any errors / notes.

mhoward2
Obsidian | Level 7

Yes the length statement correctly changes the MEMO field length to 100. But the value is still truncated to 36 characters.

FreelanceReinh
Jade | Level 19

Perhaps you inserted the FORMAT statement (without format specification) suggested by Tom before the SET statement? In this case a format of length 36 associated with variable MEMO in dataset HAVE (e.g., $36., as supposed by Tom) would make it into dataset WANT (see PROC CONTENTS output). Variable MEMO would contain the longer value, but appear truncated in PROC PRINT and other procedures' output. If this is the case, just move the FORMAT statement closer to the end of the DATA step (see Tom's DATA step).

data_null__
Jade | Level 19

I don't know this scenario is relevant.  If a variable has a format with width less than vlength it could cause what you are seeing.

 

65         data test;
66            length a $20;
67            format a $16.;
68            a = '123456789012345678901234567890';
69            l = vlength(a);
70            f = vformatw(a);
71            put 'NOTE: ' (_all_)(=);
72            put 'NOTE: ' a=$20. a=;
73            put _all_;
74            run;

NOTE: a=1234567890123456 l=20 f=16
NOTE: a=12345678901234567890 a=1234567890123456
a=1234567890123456 l=20 f=16 _ERROR_=0 _N_=1

Capture.PNG

hackathon24-white-horiz.png

2025 SAS Hackathon: There is still time!

Good news: We've extended SAS Hackathon registration until Sept. 12, so you still have time to be part of our biggest event yet – our five-year anniversary!

Register Now

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 12 replies
  • 2037 views
  • 2 likes
  • 6 in conversation