在临床编程中,经常会遇到制作注释CRF的场景。今天小编来分享一下,如何利用SAS实现注释CRF的制作。
原理
PDF的注释是可以利用PDF阅读器进行导入和导出的,利用SAS产生可导入PDF的注释文件(.xfdf)。xfdf文件内其实也是XML语言,如下图。
拿一个已经制作完成的注释CRF,将注释导出成XFDF文件,利用Notepad打开,仔细观察一下,其实很容易发现XFDF内部语句的规律。譬如<freetext>标签内的Color控制注释框的背景颜色,Page控制注释框所在页码,Rect控制注释框坐标位置(注释框长度和高度等)。当知道了每一个注释框都有类似的规律,就可以很简单的利用程序来自动生成XFDF文件了。
例子
下面来分享一下具体示例,可以利用Excel制作一个模板,填入相应的固定参数,利用SAS程序按照相应规律输出即可。
Excel模板
Excel模板列说明
关于注释框的位置,可以输入注释框一个点的位置(左上角),根据文本框的内容长度来自动计算注释框的坐标。这一步可以利用Excel公式直接得出。下面来看下我这个模板的相应的SAS程序。
代码语言:javascript复制/****************************************************************************************************************************************
宏名称 : AutoaCRF
目的 : 半自动化生成注释CRF(SDTM标准注释CRF)
参数说明 : inpath 调用模板
outpath 输出xfdf位置,输出到空白CRF同一路径下
BlackCRF 空白CRF (对应需要注释的CRF的名称)
利用Adobe PDF 阅读器导入生成xfdf即可完成注释CRF
%AutoaCRF(inpath=D:studiesSAS开发1.半自动化注释CRFExm注释CRF模板.xlsx
,outpath=D:studiesSAS开发1.半自动化注释CRFExmExm_aCRF.xfdf
,BlackCRF=Exm_aCRF.PDF);
________________________________________________________________________________________________________________________
__________________________________________________________________________________________________________________________
版本 日期 修改人 修改描述
--- ----------- ------------ ----------------------------------------------------------------------------------
1.0 2022.02.21 Setup 创建
****************************************************************************************************************************************/
%macro AutoaCRF(inpath=
,outpath=
,BlackCRF=);
proc import out = havetemp01
datafile = "&inpath."
dbms = excel replace;
range = "Sheet1$";
dbdsopts = "firstobs=1";
run;
data head;
length text $20000.;
text='<?xml version="1.0" encoding="UTF-8"?><xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve"><annots>';
run;
data end;
length text $20000.;
text='</annots><ids original="AutoaCRF" modified="AutoaCRF"/></xfdf>';
%if %length(&BlackCRF) %then %do;
text='</annots><f href="'||"&BlackCRF."||'"/><ids original="AutoaCRF" modified="AutoaCRF"/></xfdf>';
%end;
run;
data havetemp01;
set havetemp01;
_COL2=tranwrd(tranwrd(tranwrd(tranwrd(tranwrd(_COL2,'&','&'),'>','>'),'<','<'),'"','"'),"'",''');
/* _COL5 ;_COL6;*/
XY=_COL5;
run;
data havetemp02;
set havetemp01;
if ^missing(_COL2) and ^missing(_COL3);
length text text1 $20000.;
SID=compress(strip(RANUNI(_n_)));
datetime=compress(put(today(),yymmdd10.),'-')||compress(put(time(),time8.),':');
text=strip('<freetext width="1" date="D:'||strip(datetime)||'" name="'||strip(SID)||'" ' )||' color="'||strip(_COL3)||'" page="'||strip(_COL0)||'" rect="'||strip(XY)||'" subject="AutoaCRF" title="AutoaCRF">';
if _COL1="域" or upcase(_COL1)="DOMAIN" then do;
text1='<contents-richtext><body xmlns="http://www.w3.org/1999/xhtml" xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/" xfa:APIVersion="Acrobat:11.0.7" xfa:spec="2.0.2" style="font-size:16.0pt;text-align:center;color:#000000;font-weight:bold;font-style:italic;font-family:Arial;font-stretch:normal"><p dir="ltr"><span>'||strip(_COL2)||'</span></p></body></contents-richtext><defaultappearance>0 0 0 rg</defaultappearance><defaultstyle>font: Helvetica,sans-serif 12.0pt; text-align:left; color:#000000 </defaultstyle></freetext>';
end;
else do;
text1='<contents-richtext><body xmlns="http://www.w3.org/1999/xhtml" xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/" xfa:APIVersion="Acrobat:11.0.0" xfa:spec="2.0.2" style="font-size:10.0pt;text-align:left;color:#FF0000;font-weight:bold;font-style:italic;font-family:Arial;font-stretch:normal"><p dir="ltr">'||strip(_COL2)||'</p></body></contents-richtext><defaultappearance>0 0 0 rg /Arial,BoldItalic 10 Tf</defaultappearance><defaultstyle>font: italic bold Arial,sans-serif 10.0pt; text-align:left; color:#000000 </defaultstyle></freetext>';
end;
text=strip(text)||strip(text1);
keep text;
run;
data final;
set head havetemp02 end;
run;
data _null_;
set final;
file "&outpath." lrecl=20000 encoding=utf8;;
put text ;
run;
%mend;
%AutoaCRF(inpath=D:studiesSAS开发1.半自动化注释CRFExm注释CRF模板.xlsx
,outpath=D:studiesSAS开发1.半自动化注释CRFExmExm_aCRF.xfdf
,BlackCRF=Exm_aCRF.PDF);