Clinwright Public work of Helper Software LLC · free Start free

ADSL

Subject-Level Analysis

SUBJECT LEVEL ANALYSIS DATASET · one record per subject · keys USUBJID

Variables

VariableLabelTypeLengthDerivation
STUDYIDStudy IdentifiertextPredecessor DM.STUDYID
USUBJIDUnique Subject IdentifiertextPredecessor DM.USUBJID
SUBJIDSubject Identifier for the StudytextPredecessor DM.SUBJID
SITEIDStudy Site IdentifiertextPredecessor DM.SITEID
SITEGR1Pooled Site Group 1textRefer to SAP, Section 7.1. If not pooled then SITEGR1=SITEID. If pooled, SITEGR1 will be 900
ARMDescription of Planned ArmtextPredecessor DM.ARM
TRT01PPlanned Treatment for Period 01textPredecessor DM.ARM
TRT01PNPlanned Treatment for Period 01 (N)integer8Numeric code for TRT01P which corresponds to the randomized dose
TRT01AActual Treatment for Period 01textTRT01A=TRT01P, i.e., no difference between actual and randomized treatment in this study.
TRT01ANActual Treatment for Period 01 (N)integer8Numeric code for TRT01A which corresponds to the randomized dose
TRTSDTDate of First Exposure to Treatmentinteger8Date of the first dose: the earliest EX.EXSTDTC of an exposure record with a dose (or placebo), converted to a SAS date.
TRTEDTDate of Last Exposure to Treatmentinteger8Date of the last dose: the latest EX.EXENDTC of an exposure record with a dose (or placebo), converted to a SAS date.
TRTDURDTotal Treatment Duration (Days)integer8TRTEDT-TRTSDT+1
AGEAgeinteger8Predecessor DM.AGE
AGEGR1Pooled Age Group 1textCharacter variable derived from ADSL.AGEGR1N
AGEGR1NPooled Age Group 1 (N)integer8AGEGR1 = 1 if AGE <65. AGEGR1 = 2 if AGE 65-80. AGEGR1 = 3 if AGE >80.
AGEUAge UnitstextPredecessor DM.AGEU
RACERacetextPredecessor DM.RACE
RACENRace (N)integer8Numeric code for RACE
SEXSextextPredecessor DM.SEX
ETHNICEthnicitytextPredecessor DM.ETHNIC
SAFFLSafety Population FlagtextY if ITTFL='Y' and TRTSDT ne missing. N otherwise
ITTFLIntent-To-Treat Population FlagtextY if ARMCD ne ' '. N otherwise
DISCONFLDid the Subject Discontinue the Study?textY if EOSSTT='DISCONTINUED'. Null otherwise
DSRAEFLDiscontinued due to AE?textY if DCSREAS='Adverse Event'. Null otherwise
DTHFLSubject Died?textPredecessor DM.DTHFL
BMIBLBaseline BMI (kg/m^2)float8WEIGHTBL / ((HEIGHTBL*100)**2)
BMIBLGR1Pooled Baseline BMI Group 1textBMIBLGR1=Normal if . < BMIBL <25. BMIBLGR1=Overweight if 25 <=BMIBL <30. BMIBLGR1=Obese if BMIBL >=30.
HEIGHTBLBaseline Height (cm)float8VSSTRESN when VS.VSTESTCD='HEIGHT' and VS.VISITNUM=1
WEIGHTBLBaseline Weight (kg)float8VSSTRESN when VS.VSTESTCD='WEIGHT' and VS.VISITNUM=1
VISIT1DTDate of Visit 1integer8SV.SVSTDTC when SV.VISITNUM=1, converted to SAS date
RFSTDTCSubject Reference Start Date/TimedatetimePredecessor DM.RFSTDTC
RFENDTCSubject Reference End Date/TimedatetimePredecessor DM.RFENDTC
RFENDTDate of Discontinuation/Completioninteger8RFENDTC converted to SAS date
DCDECODStandardized Disposition TermtextDS.DSDECOD where DSCAT='DISPOSITION EVENT'
EOSSTTEnd of Study StatustextCOMPLETED if ADSL.DCDECOD='COMPLETED'. DISCONTINUED if ADSL.DCDECOD not equal to COMPLETED.
DCSREASReason for Discontinuation from StudytextGrouping of DCDECOD values to support summarizing study completion status and reason for discontinuation
RANDDTDate of Randomizationinteger8Date of randomization: DS.DSSTDTC of the disposition event where DSDECOD = 'RANDOMIZED', converted to a numeric SAS date; no imputation.
DTHDTDate of Deathinteger8DM.DTHDTC converted to a numeric SAS date; a missing day or month is imputed to the first.
DTHDTFDate of Death Imputation FlagtextImputation flag of DTHDT: D when the day was imputed, M when the month and day were.
LSTALVDTDate Last Known Aliveinteger8Last date the subject was known alive: the latest of AE.AESTDTC, AE.AEENDTC, LB.LBDTC and SS.SSDTC (the survival follow-up's contacts; a missing day or month imputed to the first) and TRTEDT; the dates of the domains the study has.

Program adsl.sas

Version 1, written from Clinwright's patterns, 2026-10-17, checks passed.

/*==== 00-header ====*/
/*----------------------------------------------------------------------------
  Data set : ADSL (Subject-Level Analysis)
  Reporting effort : CSR
  SDTM     : AE, DM, DS, EX, LB, SS, SV, VS
  The header and the finalize step follow from the specification.
----------------------------------------------------------------------------*/
libname sdtm "/work/sdtm" access=readonly;
libname adam "/work/adam";
options validvarname=upcase nofmterr msglevel=i;

/*==== 10-inputs ====*/
/* One record per subject of DM assigned an arm (not a screen failure: ARMCD neither SCRNFAIL nor NOTASSGN), with DM's variables. */
data work._ds;
  set sdtm.dm(where=(upcase(armcd) not in ('SCRNFAIL', 'NOTASSGN', '')));
  length trt01p $200;
  trt01p = arm;
run;
/* TRT01A: DM.ARM. */
data work._ds;
  set work._ds;
  length trt01a $200;
  trt01a = arm;
run;

/* HEIGHTBL: VS.VSSTRESN of the subject's first VS record where VSTESTCD='HEIGHT' and VISITNUM=1. */
proc sort data=sdtm.vs(where=(VSTESTCD='HEIGHT' and VISITNUM=1)) out=work._heightbl;
  by usubjid ;
run;
data work._heightbl(keep=usubjid heightbl);
  set work._heightbl;
  by usubjid;
  if first.usubjid;

  heightbl = vsstresn;

run;
data work._ds;
  merge work._ds(in=_in) work._heightbl;
  by usubjid;
  if _in;
run;

/* HEIGHTBL as the data set keeps it, for what is derived from it. */
data work._ds; set work._ds; if not missing(heightbl) then heightbl = round(heightbl, 1e-1); run;

/* WEIGHTBL: VS.VSSTRESN of the subject's first VS record where VSTESTCD='WEIGHT' and VISITNUM=1. */
proc sort data=sdtm.vs(where=(VSTESTCD='WEIGHT' and VISITNUM=1)) out=work._weightbl;
  by usubjid ;
run;
data work._weightbl(keep=usubjid weightbl);
  set work._weightbl;
  by usubjid;
  if first.usubjid;

  weightbl = vsstresn;

run;
data work._ds;
  merge work._ds(in=_in) work._weightbl;
  by usubjid;
  if _in;
run;

/* WEIGHTBL as the data set keeps it, for what is derived from it. */
data work._ds; set work._ds; if not missing(weightbl) then weightbl = round(weightbl, 1e-1); run;

/* VISIT1DT: SV.SVSTDTC of the subject's first SV record where VISITNUM=1. */
proc sort data=sdtm.sv(where=(VISITNUM=1)) out=work._visit1dt;
  by usubjid svstdtc;
run;
data work._visit1dt(keep=usubjid visit1dt);
  set work._visit1dt;
  by usubjid;
  if first.usubjid;

  visit1dt = input(substr(svstdtc, 1, 10), ?? yymmdd10.);
  format visit1dt date9.;

run;
data work._ds;
  merge work._ds(in=_in) work._visit1dt;
  by usubjid;
  if _in;
run;

/* DCDECOD: DS.DSDECOD of the subject's first DS record where DSCAT='DISPOSITION EVENT'. */
proc sort data=sdtm.ds(where=(DSCAT='DISPOSITION EVENT')) out=work._dcdecod;
  by usubjid ;
run;
data work._dcdecod(keep=usubjid dcdecod);
  set work._dcdecod;
  by usubjid;
  if first.usubjid;

  dcdecod = dsdecod;

run;
data work._ds;
  merge work._ds(in=_in) work._dcdecod;
  by usubjid;
  if _in;
run;

/*==== 20-parameters ====*/
/* TRT01PN: the code of TRT01P. */
proc format;
  invalue trt01pn_ (upcase just)

    "STANDARD OF CARE" = 1

    "CLINWRIGHTINIB 200 MG" = 2

    other = .;
run;
data work._ds;
  set work._ds;
  if trt01p ne '' then trt01pn = input(trt01p, trt01pn_.);
run;

/* TRT01AN: the code of TRT01A. */
proc format;
  invalue trt01an_ (upcase just)

    "STANDARD OF CARE" = 1

    "CLINWRIGHTINIB 200 MG" = 2

    other = .;
run;
data work._ds;
  set work._ds;
  if trt01a ne '' then trt01an = input(trt01a, trt01an_.);
run;

/* RACEN: the code of RACE. */
proc format;
  invalue racen_ (upcase just)

    "WHITE" = 1

    "BLACK OR AFRICAN AMERICAN" = 2

    "AMERICAN INDIAN OR ALASKA NATIVE" = 6

    "ASIAN" = 7

    other = .;
run;
data work._ds;
  set work._ds;
  if race ne '' then racen = input(race, racen_.);
run;

/*==== 30-timing ====*/
/* TRTSDT: the first EX.EXSTDTC of records where EXDOSE > 0 or (EXDOSE = 0 and (index(upcase(EXTRT), 'PLACEBO') > 0 or index(upcase(EXTRT), 'VEHICLE') > 0)). */
data work._ex;
  set sdtm.ex(where=(EXDOSE > 0 or (EXDOSE = 0 and (index(upcase(EXTRT), 'PLACEBO') > 0 or index(upcase(EXTRT), 'VEHICLE') > 0))));
  _dt = input(substr(exstdtc, 1, 10), ?? yymmdd10.);
  if _dt > .;
run;
proc sort data=work._ex; by usubjid _dt; run;
data work._trtsdt(keep=usubjid trtsdt);
  set work._ex;
  by usubjid;
  if first.usubjid;
  trtsdt = _dt;
  format trtsdt date9.;
run;
data work._ds;
  merge work._ds(in=_in) work._trtsdt;
  by usubjid;
  if _in;
run;

/* TRTEDT: the last EX.EXENDTC (EX.EXSTDTC when there is no end) of records where EXDOSE > 0 or (EXDOSE = 0 and (index(upcase(EXTRT), 'PLACEBO') > 0 or index(upcase(EXTRT), 'VEHICLE') > 0)). */
data work._ex;
  set sdtm.ex(where=(EXDOSE > 0 or (EXDOSE = 0 and (index(upcase(EXTRT), 'PLACEBO') > 0 or index(upcase(EXTRT), 'VEHICLE') > 0))));
  _dt = input(substr(coalescec(exendtc, exstdtc), 1, 10), ?? yymmdd10.);
  if _dt > .;
run;
proc sort data=work._ex; by usubjid _dt; run;
data work._trtedt(keep=usubjid trtedt);
  set work._ex;
  by usubjid;
  if last.usubjid;
  trtedt = _dt;
  format trtedt date9.;
run;

data work._ds;
  merge work._ds(in=_in) work._trtedt;
  by usubjid;
  if _in;
run;

/* TRTDURD: from TRTSDT to TRTEDT, in days, both days counted. */
data work._ds;
  set work._ds;
  if nmiss(trtsdt, trtedt) = 0 then trtdurd = (trtedt - trtsdt + 1);
run;

/* RFENDT: DM.RFENDTC as a SAS date. */
data work._ds;
  set work._ds;
  length _dtc $10;
  _dtc = rfendtc; /* (its first 10 characters: SUBSTR would complain of a shorter variable) */
  if length(_dtc) = 10 then rfendt = input(_dtc, ?? yymmdd10.);

  format rfendt date9.;
  drop _dtc;
run;

/* RANDDT: the date (DS.DSSTDTC) of the subject's disposition event RANDOMIZED; no imputation. */
proc sort data=sdtm.ds(where=(dsdecod = "RANDOMIZED") keep=usubjid dsdecod dsstdtc) out=work._dsdt;
  by usubjid;
run;
data work._dsdt(keep=usubjid randdt);
  set work._dsdt;
  by usubjid;
  if first.usubjid;
  if length(strip(dsstdtc)) >= 10 then randdt = input(substr(dsstdtc, 1, 10), ?? yymmdd10.);
  format randdt yymmdd10.;
run;
data work._ds;
  merge work._ds(in=_in) work._dsdt;
  by usubjid;
  if _in;
run;

/* DTHDT: DM.DTHDTC as a SAS date; a date without its day (or month) takes the first one. */
data work._ds;
  set work._ds;
  length _dtc $10;
  _dtc = dthdtc; /* (its first 10 characters: SUBSTR would complain of a shorter variable) */
  if length(_dtc) = 10 then dthdt = input(_dtc, ?? yymmdd10.);

  else if length(_dtc) = 7 then do; /* yyyy-mm */
    dthdt = input(cats(_dtc, '-01'), ?? yymmdd10.);

  end;

  else if length(_dtc) = 4 then do; /* yyyy */
    dthdt = mdy(1, 1, input(_dtc, ?? 4.));

  end;


  format dthdt date9.;
  drop _dtc;
run;

/* DTHDTF: what of DTHDT was imputed from DM.DTHDTC (set where DTHDT is imputed; see LSP-TIMING-DT). */
data work._ds;
  set work._ds;
  length dthdtf $1;
  if dthdt > . then select (length(substr(dthdtc, 1, 10)));
    when (10) dthdtf = '';
    when (7) dthdtf = 'D';
    when (4) dthdtf = 'M';
    otherwise dthdtf = '';
  end;
run;

/*==== 60-flags ====*/
/* SITEGR1: SITEID, or "900" for a site with fewer than 3 subjects in any TRT01P group. */
proc sql noprint;
  select count(distinct trt01p) into :_ls_groups trimmed from work._ds where not missing(trt01p);
  create table work._sitegr1 as
    select siteid, trt01p, count(*) as _n
    from work._ds
    where not missing(trt01p)
    group by siteid, trt01p
    order by siteid, trt01p;
quit;
data work._sitegr1(keep=siteid _pooled);
  set work._sitegr1;
  by siteid;
  retain _groups _few;
  if first.siteid then do;
    _groups = 0;
    _few = 0;
  end;
  _groups + 1;
  if _n < 3 then _few = 1;
  if last.siteid then do;
    _pooled = (_few or _groups < &_ls_groups);
    output;
  end;
run;
proc sort data=work._ds; by siteid; run;
data work._ds;
  merge work._ds(in=_in) work._sitegr1;
  by siteid;
  if _in;
  length sitegr1 $8;
  if _pooled then sitegr1 = "900";
  else sitegr1 = siteid;
  drop _pooled;
run;
proc sort data=work._ds; by usubjid; run;

/* AGEGR1: the group of AGE. */
data work._ds;
  set work._ds;

  length agegr1 $40;

  if missing(age) then call missing(agegr1);

  else if age < 65 then agegr1 = "<65";

  else if age >= 65 and age <= 80 then agegr1 = "65-80";

  else if age > 80 then agegr1 = ">80";

run;

/* AGEGR1N: the group of AGE. */
data work._ds;
  set work._ds;

  if missing(age) then call missing(agegr1n);

  else if age < 65 then agegr1n = 1;

  else if age >= 65 and age <= 80 then agegr1n = 2;

  else if age > 80 then agegr1n = 3;

run;

/* ITTFL: Y if ARMCD ne ' '; otherwise N. */
data work._ds;
  set work._ds;
  length ittfl $1;
  if ARMCD ne ' ' then ittfl = 'Y';
  else ittfl = 'N';
run;

/* SAFFL: Y if ITTFL='Y' and not missing(TRTSDT); otherwise N. */
data work._ds;
  set work._ds;
  length saffl $1;
  if ITTFL='Y' and not missing(TRTSDT) then saffl = 'Y';
  else saffl = 'N';
run;

/* BMIBL: WEIGHTBL / (HEIGHTBL/100)**2. */
data work._ds;
  set work._ds;
  if weightbl > 0 and heightbl > 0 then bmibl = weightbl / (heightbl / 100)**2;
run;

/* BMIBL as the data set keeps it, for what is derived from it. */
data work._ds; set work._ds; if not missing(bmibl) then bmibl = round(bmibl, 1e-1); run;

/* BMIBLGR1: the group of BMIBL. */
data work._ds;
  set work._ds;

  length bmiblgr1 $40;

  if missing(bmibl) then call missing(bmiblgr1);

  else if bmibl < 25 then bmiblgr1 = "<25";

  else if bmibl >= 25 and bmibl < 30 then bmiblgr1 = "25-<30";

  else if bmibl >= 30 then bmiblgr1 = ">=30";

run;

/* EOSSTT: from the subject's DS record where DSCAT = 'DISPOSITION EVENT'. */
/* The subject's last such event (a subject may have several). */
proc sort data=sdtm.ds(where=(dscat = 'DISPOSITION EVENT'))
          out=work._eosstt(keep=usubjid dsstdtc dsdecod);
  by usubjid dsstdtc;
run;
data work._eosstt(keep=usubjid _decod);
  set work._eosstt;
  by usubjid;
  if last.usubjid;
  _decod = dsdecod;
run;
data work._ds;
  merge work._ds(in=_in) work._eosstt;
  by usubjid;
  if _in;
  length eosstt $20;
  if _decod = 'COMPLETED' then eosstt = 'COMPLETED';
  else if _decod ne '' then eosstt = 'DISCONTINUED';
  else eosstt = 'ONGOING';
  drop _decod;
run;

/* DCSREAS: the reason the subject did not complete (DSDECOD of DSCAT = 'DISPOSITION EVENT'). */
/* The subject's last such event (a subject may have several). */
proc sort data=sdtm.ds(where=(dscat = 'DISPOSITION EVENT')) out=work._dcsreas(keep=usubjid dsstdtc dsdecod);
  by usubjid dsstdtc;
run;
data work._dcsreas(keep=usubjid dcsreas);
  set work._dcsreas;
  by usubjid;
  if last.usubjid and dsdecod ne 'COMPLETED';
  length dcsreas $200;

  select (upcase(dsdecod));

    when ("COMPLETED") dcsreas = "Completed";

    when ("ADVERSE EVENT") dcsreas = "Adverse Event";

    when ("DEATH") dcsreas = "Death";

    when ("I/E NOT MET") dcsreas = "I/E Not Met";

    when ("LACK OF EFFICACY") dcsreas = "Lack of Efficacy";

    when ("LOST TO FOLLOW-UP") dcsreas = "Lost to Follow-up";

    when ("PHYSICIAN DECISION") dcsreas = "Physician Decision";

    when ("PROTOCOL VIOLATION") dcsreas = "Protocol Violation";

    when ("SPONSOR DECISION") dcsreas = "Sponsor Decision";

    when ("WITHDREW CONSENT") dcsreas = "Withdrew Consent";

    when ("PROGRESSIVE DISEASE") dcsreas = "Progressive Disease";

    when ("NON-COMPLIANCE WITH STUDY DRUG") dcsreas = "Completed";

    when ("PROTOCOL DEVIATION") dcsreas = "Protocol Violation";

    when ("SITE TERMINATED BY SPONSOR") dcsreas = "Sponsor Decision";

    when ("STUDY TERMINATED BY SPONSOR") dcsreas = "Sponsor Decision";

    when ("WITHDRAWAL BY PARENT/GUARDIAN") dcsreas = "Withdrew Consent";

    when ("WITHDRAWAL BY SUBJECT") dcsreas = "Withdrew Consent";

    otherwise dcsreas = dsdecod;
  end;

run;
data work._ds;
  merge work._ds(in=_in) work._dcsreas;
  by usubjid;
  if _in;
run;

/*==== 70-other ====*/
/* DISCONFL: Y if EOSSTT='DISCONTINUED'; Null otherwise. */
data work._ds;
  set work._ds;

  length disconfl $4;



  if EOSSTT='DISCONTINUED' then disconfl = "Y";



  else disconfl = "Null";


run;

/* DSRAEFL: Y if DCSREAS='Adverse Event'; Null otherwise. */
data work._ds;
  set work._ds;

  length dsraefl $4;



  if DCSREAS='Adverse Event' then dsraefl = "Y";



  else dsraefl = "Null";


run;

/* LSTALVDT: the latest of AE.AESTDTC, AE.AEENDTC, LB.LBDTC, SS.SSDTC and TRTEDT (a partial date at its first day). */

data work._last(keep=usubjid _dt);
  length _dtc $10;
  set sdtm.ae(keep=usubjid aestdtc in=_s0) sdtm.ae(keep=usubjid aeendtc in=_s1) sdtm.lb(keep=usubjid lbdtc in=_s2) sdtm.ss(keep=usubjid ssdtc in=_s3);

  if _s0 then _dtc = aestdtc;

  if _s1 then _dtc = aeendtc;

  if _s2 then _dtc = lbdtc;

  if _s3 then _dtc = ssdtc;

  if length(_dtc) = 10 then _dt = input(_dtc, ?? yymmdd10.);
  else if length(_dtc) = 7 then _dt = input(cats(_dtc, '-01'), ?? yymmdd10.);
  else if length(_dtc) = 4 then _dt = mdy(1, 1, input(_dtc, ?? 4.));
  if _dt > .;
run;
proc sql;
  create table work._lastdt as select usubjid, max(_dt) as _last from work._last group by usubjid;
quit;

data work._ds;

  merge work._ds(in=_in) work._lastdt;
  by usubjid;
  if _in;

  lstalvdt = max(_last, trtedt);
  format lstalvdt yymmdd10.;

  drop _last;

run;

/*==== 89-final ====*/
/* The data set as derived; the finalize step keeps the specification's variables. */
data work._final;
  set work._ds;
run;

/*==== 90-finalize ====*/
/* 90-finalize: from the specification; the variables, their order and attributes are not changed here. */
/* The text variables the specification gives no length: as long as their longest value (at least 1). */
%let _len1 = 1; %let _len2 = 1; %let _len3 = 1; %let _len4 = 1; %let _len5 = 1; %let _len6 = 1; %let _len7 = 1; %let _len8 = 1; %let _len9 = 1; %let _len10 = 1; %let _len11 = 1; %let _len12 = 1; %let _len13 = 1; %let _len14 = 1; %let _len15 = 1; %let _len16 = 1; %let _len17 = 1; %let _len18 = 1; %let _len19 = 1; %let _len20 = 1; %let _len21 = 1; %let _len22 = 1; %let _len23 = 1; %let _len24 = 1; %let _len25 = 1;
data _null_;
  length _ren _asg _siz $32767;
  _dsid = open('work._final');
  if varnum(_dsid, 'STUDYID') > 0 then do; _ren = catx(' ', _ren, 'STUDYID=_rz1'); _asg = catx(' ', _asg, 'STUDYID = _rz1;');
    _siz = catx(' ', _siz, '_len1 = max(_len1, lengthn(STUDYID));'); end;
  if varnum(_dsid, 'USUBJID') > 0 then do; _ren = catx(' ', _ren, 'USUBJID=_rz2'); _asg = catx(' ', _asg, 'USUBJID = _rz2;');
    _siz = catx(' ', _siz, '_len2 = max(_len2, lengthn(USUBJID));'); end;
  if varnum(_dsid, 'SUBJID') > 0 then do; _ren = catx(' ', _ren, 'SUBJID=_rz3'); _asg = catx(' ', _asg, 'SUBJID = _rz3;');
    _siz = catx(' ', _siz, '_len3 = max(_len3, lengthn(SUBJID));'); end;
  if varnum(_dsid, 'SITEID') > 0 then do; _ren = catx(' ', _ren, 'SITEID=_rz4'); _asg = catx(' ', _asg, 'SITEID = _rz4;');
    _siz = catx(' ', _siz, '_len4 = max(_len4, lengthn(SITEID));'); end;
  if varnum(_dsid, 'SITEGR1') > 0 then do; _ren = catx(' ', _ren, 'SITEGR1=_rz5'); _asg = catx(' ', _asg, 'SITEGR1 = _rz5;');
    _siz = catx(' ', _siz, '_len5 = max(_len5, lengthn(SITEGR1));'); end;
  if varnum(_dsid, 'ARM') > 0 then do; _ren = catx(' ', _ren, 'ARM=_rz6'); _asg = catx(' ', _asg, 'ARM = _rz6;');
    _siz = catx(' ', _siz, '_len6 = max(_len6, lengthn(ARM));'); end;
  if varnum(_dsid, 'TRT01P') > 0 then do; _ren = catx(' ', _ren, 'TRT01P=_rz7'); _asg = catx(' ', _asg, 'TRT01P = _rz7;');
    _siz = catx(' ', _siz, '_len7 = max(_len7, lengthn(TRT01P));'); end;
  if varnum(_dsid, 'TRT01A') > 0 then do; _ren = catx(' ', _ren, 'TRT01A=_rz8'); _asg = catx(' ', _asg, 'TRT01A = _rz8;');
    _siz = catx(' ', _siz, '_len8 = max(_len8, lengthn(TRT01A));'); end;
  if varnum(_dsid, 'AGEGR1') > 0 then do; _ren = catx(' ', _ren, 'AGEGR1=_rz9'); _asg = catx(' ', _asg, 'AGEGR1 = _rz9;');
    _siz = catx(' ', _siz, '_len9 = max(_len9, lengthn(AGEGR1));'); end;
  if varnum(_dsid, 'AGEU') > 0 then do; _ren = catx(' ', _ren, 'AGEU=_rz10'); _asg = catx(' ', _asg, 'AGEU = _rz10;');
    _siz = catx(' ', _siz, '_len10 = max(_len10, lengthn(AGEU));'); end;
  if varnum(_dsid, 'RACE') > 0 then do; _ren = catx(' ', _ren, 'RACE=_rz11'); _asg = catx(' ', _asg, 'RACE = _rz11;');
    _siz = catx(' ', _siz, '_len11 = max(_len11, lengthn(RACE));'); end;
  if varnum(_dsid, 'SEX') > 0 then do; _ren = catx(' ', _ren, 'SEX=_rz12'); _asg = catx(' ', _asg, 'SEX = _rz12;');
    _siz = catx(' ', _siz, '_len12 = max(_len12, lengthn(SEX));'); end;
  if varnum(_dsid, 'ETHNIC') > 0 then do; _ren = catx(' ', _ren, 'ETHNIC=_rz13'); _asg = catx(' ', _asg, 'ETHNIC = _rz13;');
    _siz = catx(' ', _siz, '_len13 = max(_len13, lengthn(ETHNIC));'); end;
  if varnum(_dsid, 'SAFFL') > 0 then do; _ren = catx(' ', _ren, 'SAFFL=_rz14'); _asg = catx(' ', _asg, 'SAFFL = _rz14;');
    _siz = catx(' ', _siz, '_len14 = max(_len14, lengthn(SAFFL));'); end;
  if varnum(_dsid, 'ITTFL') > 0 then do; _ren = catx(' ', _ren, 'ITTFL=_rz15'); _asg = catx(' ', _asg, 'ITTFL = _rz15;');
    _siz = catx(' ', _siz, '_len15 = max(_len15, lengthn(ITTFL));'); end;
  if varnum(_dsid, 'DISCONFL') > 0 then do; _ren = catx(' ', _ren, 'DISCONFL=_rz16'); _asg = catx(' ', _asg, 'DISCONFL = _rz16;');
    _siz = catx(' ', _siz, '_len16 = max(_len16, lengthn(DISCONFL));'); end;
  if varnum(_dsid, 'DSRAEFL') > 0 then do; _ren = catx(' ', _ren, 'DSRAEFL=_rz17'); _asg = catx(' ', _asg, 'DSRAEFL = _rz17;');
    _siz = catx(' ', _siz, '_len17 = max(_len17, lengthn(DSRAEFL));'); end;
  if varnum(_dsid, 'DTHFL') > 0 then do; _ren = catx(' ', _ren, 'DTHFL=_rz18'); _asg = catx(' ', _asg, 'DTHFL = _rz18;');
    _siz = catx(' ', _siz, '_len18 = max(_len18, lengthn(DTHFL));'); end;
  if varnum(_dsid, 'BMIBLGR1') > 0 then do; _ren = catx(' ', _ren, 'BMIBLGR1=_rz19'); _asg = catx(' ', _asg, 'BMIBLGR1 = _rz19;');
    _siz = catx(' ', _siz, '_len19 = max(_len19, lengthn(BMIBLGR1));'); end;
  if varnum(_dsid, 'RFSTDTC') > 0 then do; _ren = catx(' ', _ren, 'RFSTDTC=_rz20'); _asg = catx(' ', _asg, 'RFSTDTC = _rz20;');
    _siz = catx(' ', _siz, '_len20 = max(_len20, lengthn(RFSTDTC));'); end;
  if varnum(_dsid, 'RFENDTC') > 0 then do; _ren = catx(' ', _ren, 'RFENDTC=_rz21'); _asg = catx(' ', _asg, 'RFENDTC = _rz21;');
    _siz = catx(' ', _siz, '_len21 = max(_len21, lengthn(RFENDTC));'); end;
  if varnum(_dsid, 'DCDECOD') > 0 then do; _ren = catx(' ', _ren, 'DCDECOD=_rz22'); _asg = catx(' ', _asg, 'DCDECOD = _rz22;');
    _siz = catx(' ', _siz, '_len22 = max(_len22, lengthn(DCDECOD));'); end;
  if varnum(_dsid, 'EOSSTT') > 0 then do; _ren = catx(' ', _ren, 'EOSSTT=_rz23'); _asg = catx(' ', _asg, 'EOSSTT = _rz23;');
    _siz = catx(' ', _siz, '_len23 = max(_len23, lengthn(EOSSTT));'); end;
  if varnum(_dsid, 'DCSREAS') > 0 then do; _ren = catx(' ', _ren, 'DCSREAS=_rz24'); _asg = catx(' ', _asg, 'DCSREAS = _rz24;');
    _siz = catx(' ', _siz, '_len24 = max(_len24, lengthn(DCSREAS));'); end;
  if varnum(_dsid, 'DTHDTF') > 0 then do; _ren = catx(' ', _ren, 'DTHDTF=_rz25'); _asg = catx(' ', _asg, 'DTHDTF = _rz25;');
    _siz = catx(' ', _siz, '_len25 = max(_len25, lengthn(DTHDTF));'); end;
  _rc = close(_dsid);
  if _ren ne '' then _ren = cats('(rename=(', _ren, '))');
  call symputx('_ren', _ren);
  call symputx('_asg', _asg);
  call symputx('_siz', _siz);
run;
data _null_;
  set work._final end=_end;
  retain _len1 1 _len2 1 _len3 1 _len4 1 _len5 1 _len6 1 _len7 1 _len8 1 _len9 1 _len10 1 _len11 1 _len12 1 _len13 1 _len14 1 _len15 1 _len16 1 _len17 1 _len18 1 _len19 1 _len20 1 _len21 1 _len22 1 _len23 1 _len24 1 _len25 1;
  &_siz
  if _end then do;
    call symputx('_len1', _len1);
    call symputx('_len2', _len2);
    call symputx('_len3', _len3);
    call symputx('_len4', _len4);
    call symputx('_len5', _len5);
    call symputx('_len6', _len6);
    call symputx('_len7', _len7);
    call symputx('_len8', _len8);
    call symputx('_len9', _len9);
    call symputx('_len10', _len10);
    call symputx('_len11', _len11);
    call symputx('_len12', _len12);
    call symputx('_len13', _len13);
    call symputx('_len14', _len14);
    call symputx('_len15', _len15);
    call symputx('_len16', _len16);
    call symputx('_len17', _len17);
    call symputx('_len18', _len18);
    call symputx('_len19', _len19);
    call symputx('_len20', _len20);
    call symputx('_len21', _len21);
    call symputx('_len22', _len22);
    call symputx('_len23', _len23);
    call symputx('_len24', _len24);
    call symputx('_len25', _len25);
  end;
run;
data adam.adsl(label="Subject-Level Analysis");
  attrib
    STUDYID  length=$&_len1 label="Study Identifier"
    USUBJID  length=$&_len2 label="Unique Subject Identifier"
    SUBJID   length=$&_len3 label="Subject Identifier for the Study"
    SITEID   length=$&_len4 label="Study Site Identifier"
    SITEGR1  length=$&_len5 label="Pooled Site Group 1"
    ARM      length=$&_len6 label="Description of Planned Arm"
    TRT01P   length=$&_len7 label="Planned Treatment for Period 01"
    TRT01PN  length=8 label="Planned Treatment for Period 01 (N)"
    TRT01A   length=$&_len8 label="Actual Treatment for Period 01"
    TRT01AN  length=8 label="Actual Treatment for Period 01 (N)"
    TRTSDT   length=8 label="Date of First Exposure to Treatment" format=DATE9.
    TRTEDT   length=8 label="Date of Last Exposure to Treatment" format=DATE9.
    TRTDURD  length=8 label="Total Treatment Duration (Days)"
    AGE      length=8 label="Age"
    AGEGR1   length=$&_len9 label="Pooled Age Group 1"
    AGEGR1N  length=8 label="Pooled Age Group 1 (N)"
    AGEU     length=$&_len10 label="Age Units"
    RACE     length=$&_len11 label="Race"
    RACEN    length=8 label="Race (N)"
    SEX      length=$&_len12 label="Sex"
    ETHNIC   length=$&_len13 label="Ethnicity"
    SAFFL    length=$&_len14 label="Safety Population Flag"
    ITTFL    length=$&_len15 label="Intent-To-Treat Population Flag"
    DISCONFL length=$&_len16 label="Did the Subject Discontinue the Study?"
    DSRAEFL  length=$&_len17 label="Discontinued due to AE?"
    DTHFL    length=$&_len18 label="Subject Died?"
    BMIBL    length=8 label="Baseline BMI (kg/m^2)"
    BMIBLGR1 length=$&_len19 label="Pooled Baseline BMI Group 1"
    HEIGHTBL length=8 label="Baseline Height (cm)"
    WEIGHTBL length=8 label="Baseline Weight (kg)"
    VISIT1DT length=8 label="Date of Visit 1" format=DATE9.
    RFSTDTC  length=$&_len20 label="Subject Reference Start Date/Time"
    RFENDTC  length=$&_len21 label="Subject Reference End Date/Time"
    RFENDT   length=8 label="Date of Discontinuation/Completion" format=DATE9.
    DCDECOD  length=$&_len22 label="Standardized Disposition Term"
    EOSSTT   length=$&_len23 label="End of Study Status"
    DCSREAS  length=$&_len24 label="Reason for Discontinuation from Study"
    RANDDT   length=8 label="Date of Randomization" format=DATE9.
    DTHDT    length=8 label="Date of Death" format=DATE9.
    DTHDTF   length=$&_len25 label="Date of Death Imputation Flag"
    LSTALVDT length=8 label="Date Last Known Alive" format=DATE9.
  ;
  set work._final&_ren;
  &_asg
  if not missing(BMIBL) then BMIBL = round(BMIBL, 1e-1);
  if not missing(HEIGHTBL) then HEIGHTBL = round(HEIGHTBL, 1e-1);
  if not missing(WEIGHTBL) then WEIGHTBL = round(WEIGHTBL, 1e-1);
  keep STUDYID USUBJID SUBJID SITEID SITEGR1 ARM TRT01P TRT01PN TRT01A TRT01AN TRTSDT TRTEDT TRTDURD AGE AGEGR1 AGEGR1N AGEU RACE RACEN SEX ETHNIC SAFFL ITTFL DISCONFL DSRAEFL DTHFL BMIBL BMIBLGR1 HEIGHTBL WEIGHTBL VISIT1DT RFSTDTC RFENDTC RFENDT DCDECOD EOSSTT DCSREAS RANDDT DTHDT DTHDTF LSTALVDT;
run;
proc sort data=adam.adsl; by USUBJID; run;

Data (first 20 of 300 records, simulated)

STUDYIDUSUBJIDSUBJIDSITEIDSITEGR1ARMTRT01PTRT01PNTRT01ATRT01ANTRTSDTTRTEDTTRTDURDAGEAGEGR1AGEGR1NAGEURACERACENSEXETHNICSAFFLITTFLDISCONFLDSRAEFLDTHFLBMIBLBMIBLGR1HEIGHTBLWEIGHTBLVISIT1DTRFSTDTCRFENDTCRFENDTDCDECODEOSSTTDCSREASRANDDTDTHDTDTHDTFLSTALVDT
ONCO-EXONCO-EX-701002701002701701Standard of CareStandard of Care1Standard of Care12022-02-122022-12-1030257<651YEARSWHITE1FNOT HISPANIC OR LATINOYYYNull20<25167.255.82022-02-092022-02-122022-12-102022-12-10PROGRESSIVE DISEASEDISCONTINUEDProgressive Disease2022-02-112023-12-10
ONCO-EXONCO-EX-701003701003701701Standard of CareStandard of Care1Standard of Care12022-03-172022-10-2021858<651YEARSWHITE1MNOT HISPANIC OR LATINOYYYNull22.7<25160.558.52022-02-202022-03-172022-10-202022-10-20PROGRESSIVE DISEASEDISCONTINUEDProgressive Disease2022-03-162023-10-20
ONCO-EXONCO-EX-701004701004701701Clinwrightinib 200 mgClinwrightinib 200 mg2Clinwrightinib 200 mg22022-03-182023-02-1633660<651YEARSWHITE1MNOT HISPANIC OR LATINOYYNullNull32.1>=30151.173.42022-03-102022-03-182023-02-162023-02-16COMPLETEDCOMPLETED2022-03-172024-02-16
ONCO-EXONCO-EX-701005701005701701Clinwrightinib 200 mgClinwrightinib 200 mg2Clinwrightinib 200 mg22022-03-312023-03-0133662<651YEARSWHITE1MNOT HISPANIC OR LATINOYYNullNull23<25160.559.32022-03-262022-03-312023-03-012023-03-01COMPLETEDCOMPLETED2022-03-302024-02-29
ONCO-EXONCO-EX-701007701007701701Standard of CareStandard of Care1Standard of Care12022-04-192023-02-1430263<651YEARSWHITE1MHISPANIC OR LATINOYYYNullY19.5<25172.758.22022-03-292022-04-192023-02-142023-02-14PROGRESSIVE DISEASEDISCONTINUEDDeath2022-04-182023-10-042023-08-06
ONCO-EXONCO-EX-701008701008701701Clinwrightinib 200 mgClinwrightinib 200 mg2Clinwrightinib 200 mg22022-04-262022-11-2921854<651YEARSWHITE1MNOT HISPANIC OR LATINOYYYNullY27.425-<30159.8702022-04-092022-04-262022-11-292022-11-29PROGRESSIVE DISEASEDISCONTINUEDDeath2022-04-252022-12-212022-11-29
ONCO-EXONCO-EX-701009701009701701Clinwrightinib 200 mgClinwrightinib 200 mg2Clinwrightinib 200 mg22022-04-182022-11-2121858<651YEARSBLACK OR AFRICAN AMERICAN2MNOT HISPANIC OR LATINOYYYNull15.2<25165.341.42022-04-142022-04-182022-11-212022-11-21PROGRESSIVE DISEASEDISCONTINUEDProgressive Disease2022-04-172023-11-21
ONCO-EXONCO-EX-701010701010701701Clinwrightinib 200 mgClinwrightinib 200 mg2Clinwrightinib 200 mg22022-06-102023-05-1133664<651YEARSWHITE1FNOT HISPANIC OR LATINOYYNullNull21.8<25176.968.22022-05-282022-06-102023-05-112023-05-11COMPLETEDCOMPLETED2022-06-092024-05-10
ONCO-EXONCO-EX-701011701011701701Clinwrightinib 200 mgClinwrightinib 200 mg2Clinwrightinib 200 mg22022-06-162022-08-045062<651YEARSWHITE1MNOT HISPANIC OR LATINOYYYNull2525-<30167.670.32022-06-082022-06-162022-08-042022-08-04PROGRESSIVE DISEASEDISCONTINUEDProgressive Disease2022-06-152023-08-04
ONCO-EXONCO-EX-701012701012701701Standard of CareStandard of Care1Standard of Care12022-06-282022-12-201766565-802YEARSWHITE1FNOT HISPANIC OR LATINOYYYNull21<25171.361.52022-06-142022-06-282022-12-202022-12-20PROGRESSIVE DISEASEDISCONTINUEDProgressive Disease2022-06-272023-12-20
ONCO-EXONCO-EX-701014701014701701Clinwrightinib 200 mgClinwrightinib 200 mg2Clinwrightinib 200 mg22022-07-032023-06-0333688>803YEARSWHITE1MNOT HISPANIC OR LATINOYYNullNull17.7<25174.253.82022-06-152022-07-032023-06-032023-06-03COMPLETEDCOMPLETED2022-07-022024-06-02
ONCO-EXONCO-EX-701015701015701701Clinwrightinib 200 mgClinwrightinib 200 mg2Clinwrightinib 200 mg22022-07-102023-03-262606665-802YEARSWHITE1MNOT HISPANIC OR LATINOYYYNull26.425-<30168.7752022-07-052022-07-102023-03-262023-03-26PROGRESSIVE DISEASEDISCONTINUEDProgressive Disease2022-07-092024-03-25
ONCO-EXONCO-EX-701016701016701701Standard of CareStandard of Care1Standard of Care12022-07-082023-06-0833658<651YEARSWHITE1FNOT HISPANIC OR LATINOYYNullNull17<25165.246.52022-06-252022-07-082023-06-082023-06-08COMPLETEDCOMPLETED2022-07-072024-06-07
ONCO-EXONCO-EX-701017701017701701Standard of CareStandard of Care1Standard of Care12022-07-152022-09-025045<651YEARSWHITE1MNOT HISPANIC OR LATINOYYYNullY30.9>=30169.588.72022-07-032022-07-152022-09-022022-09-02PROGRESSIVE DISEASEDISCONTINUEDDeath2022-07-142022-12-022022-11-29
ONCO-EXONCO-EX-701018701018701701Clinwrightinib 200 mgClinwrightinib 200 mg2Clinwrightinib 200 mg22022-08-022023-01-2417662<651YEARSWHITE1MNOT HISPANIC OR LATINOYYYNullY24.4<25167.268.32022-07-232022-08-022023-01-242023-01-24PROGRESSIVE DISEASEDISCONTINUEDDeath2022-08-012023-03-112023-01-24
ONCO-EXONCO-EX-701020701020701701Clinwrightinib 200 mgClinwrightinib 200 mg2Clinwrightinib 200 mg22022-08-172022-10-05507465-802YEARSWHITE1FNOT HISPANIC OR LATINOYYYNull2925-<30146.762.52022-07-282022-08-172022-10-052022-10-05PROGRESSIVE DISEASEDISCONTINUEDProgressive Disease2022-08-162023-10-05
ONCO-EXONCO-EX-701021701021701701Clinwrightinib 200 mgClinwrightinib 200 mg2Clinwrightinib 200 mg22022-08-052022-09-23506765-802YEARSWHITE1FNOT HISPANIC OR LATINOYYYNull20<25176.161.92022-07-272022-08-052022-09-232022-09-23PROGRESSIVE DISEASEDISCONTINUEDProgressive Disease2022-08-042023-09-23
ONCO-EXONCO-EX-701022701022701701Standard of CareStandard of Care1Standard of Care12022-08-132023-04-2926059<651YEARSWHITE1MNOT HISPANIC OR LATINOYYYNull24.5<25169702022-07-232022-08-132023-04-292023-04-29PROGRESSIVE DISEASEDISCONTINUEDProgressive Disease2022-08-122024-04-28
ONCO-EXONCO-EX-701023701023701701Standard of CareStandard of Care1Standard of Care12022-08-012022-09-195052<651YEARSWHITE1MNOT HISPANIC OR LATINOYYYNull13.1<25165.9362022-07-242022-08-012022-09-192022-09-19PROGRESSIVE DISEASEDISCONTINUEDProgressive Disease2022-07-312023-09-19
ONCO-EXONCO-EX-701024701024701701Standard of CareStandard of Care1Standard of Care12022-09-042022-10-144160<651YEARSWHITE1FNOT HISPANIC OR LATINOYYYNull22.8<25171.967.42022-08-082022-09-042022-10-232022-10-23PROGRESSIVE DISEASEDISCONTINUEDProgressive Disease2022-09-032023-10-23