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!
@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.
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 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.
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?
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.
@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?
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.
Yes the length statement correctly changes the MEMO field length to 100. But the value is still truncated to 36 characters.
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).
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
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!
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.
Ready to level-up your skills? Choose your own adventure.