2017-04-25 57 views
1

我試圖用Python 2.7的docx模塊填寫word文檔表單。我可以修改文本元素,但我很難理解如何檢查是或否複選框。用Python使用docx模塊檢查.docx格式的複選框

我該如何去檢查一個表單中的複選框。我嘗試了一些不同的方法,但我認爲這一切都對我有用,但不知道docx xml是如何在複選框中構建的。

我可以使用書籤屬性來查找特定複選框,並按照下圖所示檢查它嗎?

enter image description here

我已經上傳測試表格的副本,以谷歌驅動here

回答

1

好吧,經過很多挫折後,我終於想出瞭如何檢查複選框。複選框元素中有一個元素,表示該複選框是否被選中。我基本上可以用下面的函數創建這個元素。

from docx.oxml import OxmlElement 
from docx.oxml.ns import qn 

def checkedElement(): 
    elm = OxmlElement('w:checked') 
    elm.set(qn('w:val'),"true") 
    return elm 

我可以使用下面的函數找到表格單元格內的所有複選框。由於是總是在每個單元中的第一個複選框,我可以設置在索引中是檢查爲0,且沒有檢查索引1,然後我可以追加複選框元素中選中的元素:

def yesNoCheck(yes_no,tableIdx,coords): 
    print coords, yes_no 
    if yes_no == 'y': 
     index = 0 
     x = doc.tables[tableIdx].cell(coords[0],coords[1])._element.xpath('.//w:checkBox') 
     x[index].append(checkedElement()) 
    elif yes_no == 'n': 
     index = 1 
     x = doc.tables[tableIdx].cell(coords[0],coords[1])._element.xpath('.//w:checkBox') 
     x[index].append(checkedElement()) 
    else: 
     print "value was neither yes or no" 
     pass 

這裏是我到目前爲止編寫的完整代碼。我有一堆重構要做,但它現在工作的很好。我的.docx模板中有兩個表,字典table1和table2包含單元格的行和列座標。該腳本用於使用ESRI Survey123發佈的數據填寫所需的表單。

from docx import Document 
from docx.oxml import OxmlElement 
from docx.oxml.ns import qn 
from docx.shared import Inches 
from docx.enum.text import WD_ALIGN_PARAGRAPH 
import arcpy 
import datetime 
import os 

table1 = { 
    'BusinessName':[2,3], 
    'LicenseNumber':[2,14], 
    'OwnerName':[3,3], 
    'PhoneNumber':[3,14], 
    'BusinessAddress':[4,5], 
    'County':[4,14], 
    'City':[5,1], 
    'St':[5,8], 
    'Zip':[5,15], 
    'LicenceExpired':[6,1], #CheckBox 
    'DateExpired':[6,15], 
    'LicenceRenewal':[7,1], #CheckBox 
    'NumberDisplayed':[8,1], #CheckBox 
    'NameAddDisplayed':[10,1], #CheckBox 
    'VehicleInfoMatches':[12,1], #CheckBox 
    'DischargeValveCapped':[14,1], #CheckBox 
    'DischargeValveCapChained':[15,1], #CheckBox 
    'HoseDisinfectCarried':[16,1], #CheckBox 
    'VehicleAndTankClean':[17,1], #CheckBox 
    'FreeOfLeaks':[18,1] #CheckBox 
} 

table2 = { 
    'LandApplyWaste':[1,1], #Yes/No CheckBox 
    'LocationDescriptionAccurate':[6,1], #Yes/No CheckBox 
    'LocationDescriptionAccDesc':[6,5], #text 
    'Slope':[7,1], #Yes/No CheckBox 
    'DistanceNearestResidence':[8,1], #Yes/No CheckBox 
    'DistanceNearestWell':[9,1], #Yes/No CheckBox 
    'DistanceNearestStreamLakeEtc':[10,1], #Yes/No CheckBox 
    'SeptageIncorporated':[11,1], #Yes/No CheckBox 
    'InjectedIncorporated':[12,3], #Yes/No CheckBox, dependent on the septage incorporated being yes 
    'SeptageStabilized':[13,1], #Yes/No CheckBox 
    'HowIsLimeMixed':[14,3], #text dependent on if lime was used 
    'ConfiningLayerOrGroundwater':[15,1], #Yes/No CheckBox 
    'ConfiningLayerOrGroundwaterDesc':[16,3], #text 
    'CropGrown':[17,1], #Yes/No CheckBox 
    'CropGrownHowVerified':[19,3], #text 
    'LandAppCompliance':[20,1], #Yes/No CheckBox 
    'AdditionalComments':[22,3], 
    'SignDate':[22,13] 
} 

def checkedElement(): 
    elm = OxmlElement('w:checked') 
    elm.set(qn('w:val'),"true") 
    return elm 

def yesNoCheck(yes_no,tableIdx,coords): 
    print coords, yes_no 
    if yes_no == 'y': 
     index = 0 
     x = doc.tables[tableIdx].cell(coords[0],coords[1])._element.xpath('.//w:checkBox') 
     x[index].append(checkedElement()) 
    elif yes_no == 'n': 
     index = 1 
     x = doc.tables[tableIdx].cell(coords[0],coords[1])._element.xpath('.//w:checkBox') 
     x[index].append(checkedElement()) 
    else: 
     print "value was neither yes or no" 
     pass 

def disposalMethodCheck(method, locationDec): 
    vals = { 
     'WastewaterTreatmentFacility':[20,1], 
     'LandApplication':[22,1], 
     'SanitaryLandfill':[24,1], 
     'SeptageLagoonOrDryingBed':[26,1] 
    } 
    if method != None: 
     row,col = vals[method] 
     checkBoxElm = doc.tables[0].cell(row,col)._element.xpath('.//w:checkBox')[0] 
     print "{0} Checked!".format(method) 
     checkBoxElm.append(checkedElement()) 
     editTxt(locationDec,0,[row,6]) 

def editTxt(text, tblIdx, coords, alignment = WD_ALIGN_PARAGRAPH.LEFT, bold=True): 
    print text, coords 
    field = doc.tables[tblIdx].cell(coords[0],coords[1]).paragraphs[0] 
    field.text = text 
    field.alignment = alignment 
    field.runs[0].font.bold = bold 

def addSig(sigJpgPath): 
    para = doc.tables[1].row_cells(23)[0].paragraphs[0] 
    para.alignment = WD_ALIGN_PARAGRAPH.CENTER 
    run = para.add_run() 
    run.add_picture(sigJpgPath,width=Inches(1.34),height=Inches(.35)) 

fc = r"E:\PumperTruckInspectionFeatureClass" 
arcpy.MakeFeatureLayer_management (fc, "PumperTruckInspections") 
attach = r"PumperTruckInspection__ATTACH" #Where signatures are stored 

def rows_as_dicts(cursor): 
    colnames = cursor.fields 
    for row in cursor: 
     yield dict(zip(colnames, row)) 

def dateString(date): 
    if date != None: 
     d = date.strftime('%m/%d/%Y') 
     return d 
    else: 
     print "no date" 
     return '' 

def checkBusName(name): 
    if name != None: 
     return name 
    else: 
     return 'unknown' 

with arcpy.da.SearchCursor(fc, '*') as sc: 
    for row in rows_as_dicts(sc): 
     doc = Document(r"path\to\TEMPLATE.docx") 

     t = datetime.datetime.now().strftime('%Y-%m-%d') 
     newDocName = checkBusName(row['BusinessName']) + t + '.docx' 


     editTxt(row['BusinessName'],0,table1['BusinessName']) 
     editTxt(row['LicenseNumber'],0,table1['LicenseNumber']) 
     editTxt(row['OwnerName'],0,table1['OwnerName']) 
     editTxt(row['PhoneNumber'],0,table1['PhoneNumber']) 
     editTxt(row['BusinessAddress'],0,table1['BusinessAddress']) 
     editTxt(row['County'],0,table1['County']) 
     editTxt(row['City'],0,table1['City']) 
     editTxt(row['St'],0,table1['St']) 
     editTxt(row['Zip'],0,table1['Zip']) 
     editTxt(dateString(row['DateExpired']),0,table1['DateExpired']) 
     yesNoCheck(row['LicenceExpired'],0, table1['LicenceExpired']) 

     yesNoCheck(row['LicenceRenewal'],0, table1['LicenceRenewal']) 
     yesNoCheck(row['NumberDisplayed'],0, table1['NumberDisplayed']) 
     yesNoCheck(row['NameAddDisplayed'],0, table1['NameAddDisplayed']) 
     yesNoCheck(row['VehicleInfoMatches'],0, table1['VehicleInfoMatches']) 
     yesNoCheck(row['DischargeValveCapped'],0, table1['DischargeValveCapped']) 
     yesNoCheck(row['DischargeValveCapChained'],0, table1['DischargeValveCapChained']) 
     yesNoCheck(row['HoseDisinfectCarried'],0, table1['HoseDisinfectCarried']) 
     yesNoCheck(row['VehicleAndTankClean'],0, table1['VehicleAndTankClean']) 
     yesNoCheck(row['FreeOfLeaks'],0, table1['FreeOfLeaks']) 
     disposalMethodCheck(row['DisposalMethod'],row['DisposalLocation']) 
     if row['DisposalMethod'] == 'LandApplication': 
      yesNoCheck(row['LandApplyWaste'],1,table2['LandApplyWaste']) 
      yesNoCheck(row['LocationDescriptionAccurate'],1,table2['LocationDescriptionAccurate']) 
      editTxt(row['LocationDescriptionAccDesc'],1,table2['LocationDescriptionAccDesc']) 
      yesNoCheck(row['Slope'],1,table2['Slope']) 
      yesNoCheck(row['DistanceNearestResidence'],1,table2['DistanceNearestResidence']) 

      yesNoCheck(row['DistanceNearestWell'],1,table2['DistanceNearestWell']) 
      yesNoCheck(row['DistanceNearestStreamLakeEtc'],1,table2['DistanceNearestStreamLakeEtc']) 
      yesNoCheck(row['SeptageIncorporated'],1,table2['SeptageIncorporated']) 
      yesNoCheck(row['InjectedIncorporated'],1,table2['InjectedIncorporated']) #might need a new method since its not yes/no 
      yesNoCheck(row['SeptageStabilized'],1,table2['SeptageStabilized']) 
      editTxt(row['HowIsLimeMixed'],1,table2['HowIsLimeMixed']) 
      yesNoCheck(row['ConfiningLayerOrGroundwater'],1,table2['ConfiningLayerOrGroundwater']) 
      editTxt(row['ConfiningLayerOrGroundwaterDescript'],1,table2['ConfiningLayerOrGroundwaterDescript']) 
      yesNoCheck(row['CropGrown'],1,table2['CropGrown']) 
      editTxt(row['CropGrownHowVerified'],1,table2['CropGrownHowVerified']) 
      yesNoCheck(row['LandAppCompliance'],1,table2['LandAppCompliance']) 
     editTxt(row['AdditionalComments'],1,table2['AdditionalComments'],bold=False) 
     where = "REL_GLOBALID = '{0}'".format(row['GlobalID']) 
     from pprint import pprint 
     with arcpy.da.SearchCursor(attach,['DATA', 'ATT_NAME', 'ATTACHMENTID'],where_clause=where) as cursor: 
      for r in rows_as_dicts(cursor): 
       pprint(r) 
       name = r['ATT_NAME'] 
       attachment = r['DATA'] 
       if name.split('_')[0] == 'InspectorSignature': 
        imagePath = os.path.join(name.split('_')[0] + "_" +) 
        open(("sig.jpeg"), 'wb').write(attachment.tobytes()) 
        addSig("sig.jpeg") 

        break 

     editTxt(dateString(row['SignDate']),1,table2['SignDate'],alignment = WD_ALIGN_PARAGRAPH.CENTER,bold=False) 
     doc.save(newDocName) 
     del doc