Python用于临床数据管理-CRF排版

'''
注意事项:
1、流程图必须不包含合并单元格,一列对应一个访视,一行对应一个表单;
2、所需表单的单元格不为空即可,不需要的表单对应的单元格为空;
3、流程图中表单的顺序需要与unique CRF文件中表格的顺序一致,名称可以不一致;
4、程序会根据流程图第一行设置页眉中的访视信息,根据流程图第二行设置页眉中的时间窗信息,其余信息请添加在CRF文件最后一个表格中,作为页眉模板;
5、流程图A1单元格内容必须为“访视编号”;
6、用户界面中;流程图路径和CRF路径请输入完整的文件路径,包含文件拓展名;(也可点击按钮选取)
7、输出文件路径仅需文件夹路径,末尾不加’\‘;
8、输出文件中若某些表格无表框,可在原始CRF文件中将表格复制到excel中再复制回来,重新运行即可;建议直接在excel中构建CRF。不要使用特殊格式的表格;
9、页眉文字若出现粗细不一致,更改字体即可一致;
10、页码请单独添加;
11、若需横排页面请手动完成;
'''


#导入所需的库——————————————————————————————————————————
from copy import deepcopy  #用于复制表格
from docx import Document #操作word文件
import docx   #操作word文件
import copy
import pandas as pd  #读取流程图文件
import tkinter as tk  #构建用户界面
import tkinter.messagebox  #输出弹窗
import threading   #线程
from docx.shared import Cm  #页眉格式
from docx.oxml.ns import qn  #字体
from tkinter import filedialog,dialog
import os
#主函数-------------------------------------------------------------------------------------
mpath='NA'
cpath='NA'
opath='NA'
def met():
    global mpath
    mpath=filedialog.askopenfilename()
    en1.insert('insert',mpath)
    print(mpath)
def uniq():
    global cpath
    cpath=filedialog.askopenfilename()
    en2.insert('insert',cpath)
def outf():
    global opath
    opath=filedialog.askdirectory()
    en3.insert('insert',opath)
def thread_it(func, *args): 
    '''将函数打包进线程'''
    # 创建
    t = threading.Thread(target=func, args=args) 
    # 守护 !!!
    t.setDaemon(True) 
    # 启动
    t.start()
    # 阻塞--卡死界面!

def getpath():
    try: #用于输出错误信息
        global mpath,cpath,opath,tel
        mpath=en1.get()  #获取流程图文件路径
        cpath=en2.get()  #获取CRF文件路径
        opath=en3.get()+'\outfile.docx'  #获取输出路径
        print(mpath,cpath,opath)
#根据流程图构建每一个表单对应的序号的字典
        metrics=pd.read_excel(mpath)  
        form={}  
        for i in range(len(metrics)):
            if metrics['访视编号'][i] not in form.keys():
                form[metrics['访视编号'][i]]=i
        print(form)
#读取CRF文件,获取其中的表格
        outfile=docx.Document()   
        filename=cpath
        document=Document(filename)
        tab=document.tables
#按流程列循环每一个访视
        for i in metrics.columns:
            print(i)
            te1.insert('insert',i)
            te1.insert('insert','\n')
            te1.see('end')
            if i=='访视编号':
                continue
            outfile.add_heading(i,level=1)
#如果某一访视某一表单对应的单元格内不为空,则将对应的表格添加到输出文件中
            for n in range(1,len(metrics)):
                if metrics[i][n]==metrics[i][n]:
                    te1.insert('insert','    '+metrics['访视编号'][n])
                    te1.insert('insert','\n')
                    te1.see('end')
                    outfile.add_heading(metrics['访视编号'][n],level=2)
                    table=tab[form[metrics['访视编号'][n-1]]]
                    newtable=deepcopy(table)
                    paragraph=outfile.add_paragraph()
                    paragraph._p.addnext(newtable._element)
                    outfile.add_page_break()
            if i != metrics.columns[-1]:  #如果不是最后一个访视,那么久在结尾添加分节符
                outfile.add_section()
        header_table = tab[-1]
        visit=list(metrics.columns)
#将CRF文件中最后一个表格作为页眉模板,访视信息和时间窗根据流程图前两行获取
        flag=0
        for section in outfile.sections:
            if flag !=0:
                section.header.is_linked_to_previous=False
            print('section{}'.format(flag))
            header = section.header
            header_table.cell(0,2).text=visit[flag+1]
            header_table.cell(1,2).text=metrics[visit[flag+1]][0]
            print(header_table.cell(0,2).text)
            print(header_table.cell(1,2).text)
            te1.insert('insert',header_table.cell(0,2).text)
            te1.insert('insert',header_table.cell(1,2).text)
            te1.insert('insert','\n')
            te1.see('end')
            new_table = deepcopy(header_table)
            new_table.autofit = True
            paragraph = header.paragraphs[0]
            paragraph._p.addnext(new_table._element)
            header.header_distance = Cm(1.2)
            flag+=1
#设置文件字体为宋体
        outfile.styles['Normal'].font.name = u'宋体'
        outfile.styles['Normal']._element.rPr.rFonts.set(qn('w:eastAsia'), u'宋体')
#保存输出文件,弹窗提示运行完成
        outfile.save(opath)
        tk.messagebox.showinfo('提示','运行完成')
#若运行出错,输出报错信息
    except Exception as e: te1.insert('insert',e)
    
#GUI界面-------------------------------------------------------------------------
window=tk.Tk()
window.geometry('800x500')
window.title('CRF排版')
bu2=tk.Button(window,text='点击选择流程图文件:',width=25,command=met)
bu2.grid(row=0,column=0)
en1=tk.Entry(window,width=70)
en1.grid(row=0,column=1)
bu3=tk.Button(window,text='点击选择Unique CRF文件:',width=25,command=uniq)
bu3.grid(row=1,column=0)
en2=tk.Entry(window,width=70)
en2.grid(row=1,column=1)
bu3=tk.Button(window,text='点击选择结果输出文件夹:',width=25,command=outf)
bu3.grid(row=2,column=0)
en3=tk.Entry(window,width=70)
en3.grid(row=2,column=1)
te1=tk.Text(window)
te1.grid(row=4,column=1)
bu1=tk.Button(window,text='运行程序',command=lambda:thread_it(getpath))
bu1.grid(row=3,column=1)
lab3=tk.Label(window,text='程序运行信息:')
lab3.grid(row=4,column=0)


window.mainloop()


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值