You may have noticed that the new variables are created in the same order they are found in the data. So you just need to make sure that the ID values are in the right order. But that can be difficult if the BY levels don't have rows for all the ID values.
If the data are from a summary you can use techniques to insure all LEVELS are created in the output. See COMPLETETYPES and PRELOADFMT in PROC SUMMAY or SPARSE option in PROC FREQ.
Sometimes that’s not an option; in that case I usually just create a special BY group that includes all values of the ID variable.
This example creates lots of data to make the point clear, I hope. It may not model your data very well but then you didn't give example data.
[pre]
proc plan seed=437500408;
factors
USUBJID = 10 ordered
year = 1 of 3
month = 4 of 12
y = 1 of 100
/ noprint;
output out=sime year nvals=(2007 2008 2009);
run;
data sime;
set sime;
date = mdy(month,1,year);
format date yymmn.;
run;
proc print;
run;
** The default PROC TRANSPOSE;
proc transpose data=sime out=wide1;
by USUBJID;
var y;
id date;
idlabel date;
run;
proc contents order=varnum;
run;
** Create special ID=. with values of DATE to establish the proper variable order.;
proc summary data=sime;
output out=dateinfo(drop=_:) min(date)=min max(date)=max;
run;
data sime2 / view=sime2;
if 0 then set sime;
set dateinfo;
do date = min to max;
output;
date = intnx('month',date,0,'end');
end;
do until(eof);
set sime end=eof;
output;
end;
stop;
run;
proc transpose data=sime2 out=wide2(where=(not missing(USUBJID)));
by USUBJID;
var y;
id date;
idlabel date;
run;
proc contents order=varnum;
run;
proc print;
run;
[/pre]
I've found if you copy and paste code that is bounded by the pre and /pre directives as above into EE the linefeeds are lost. If you first past to WORD then copy and paste to EE the linefeeds are preserved.