partReport.py 147 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520
  1. import pandas as pd
  2. import numpy as np
  3. import time
  4. import os
  5. from docx.enum.style import WD_STYLE_TYPE
  6. from docx.shared import Inches
  7. from docx.shared import Pt, RGBColor
  8. from docx import Document
  9. from docx.enum.table import WD_TABLE_ALIGNMENT, WD_CELL_VERTICAL_ALIGNMENT
  10. from docx.oxml.ns import qn
  11. from docx.enum.text import WD_ALIGN_PARAGRAPH
  12. from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
  13. import report
  14. from datetime import datetime
  15. import cn2an
  16. # 频度信息表生成
  17. def makeInfoTable(data, doc):
  18. rows = (int(len(data.columns) / 6) + 1)
  19. columnsList = np.arange(0, rows * 6, 6)
  20. dataList = []
  21. for i in columnsList:
  22. res = data.iloc[:, i:i + 6]
  23. res = res.reset_index()
  24. dataList.append(res)
  25. table_f_2 = doc.add_table(rows=rows * 6, cols=7, style='Light Shading Accent 1')
  26. for i, row in enumerate(table_f_2.rows):
  27. for j, cell in enumerate(row.cells):
  28. # 获取单元格中的段落对象
  29. paragraph = cell.paragraphs[0]
  30. if i == columnsList[0]:
  31. # 第一行 显示前6个指标的列名
  32. if len(dataList[0].columns) > j:
  33. r = paragraph.add_run(dataList[0].columns[j])
  34. r.font.bold = True
  35. r.font.size = Pt(10.5)
  36. r.font.name = 'Times New Roman'
  37. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  38. else:
  39. paragraph.add_run('')
  40. elif len(columnsList) > 1 and i > columnsList[0] and i < columnsList[1]:
  41. if len(dataList[0].columns) > j:
  42. r = paragraph.add_run(str(dataList[0].iloc[i - 1, j]))
  43. r.font.size = Pt(10.5)
  44. r.font.name = 'Times New Roman'
  45. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  46. else:
  47. paragraph.add_run('')
  48. elif i == columnsList[1]:
  49. # 第6行 显示前6个指 标的列名
  50. if len(dataList[1].columns) > j:
  51. r = paragraph.add_run(dataList[1].columns[j])
  52. r.font.bold = True
  53. r.font.size = Pt(10.5)
  54. r.font.name = 'Times New Roman'
  55. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  56. else:
  57. paragraph.add_run('')
  58. elif len(columnsList) > 2 and i > columnsList[1] and i < columnsList[2]:
  59. if len(dataList[1].columns) > j:
  60. r = paragraph.add_run(str(dataList[1].iloc[i - 7, j]))
  61. r.font.size = Pt(10.5)
  62. r.font.name = 'Times New Roman'
  63. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  64. else:
  65. paragraph.add_run('')
  66. elif i == columnsList[2]:
  67. # 第6*2行 显示前6个指 标的列名
  68. if len(dataList[2].columns) > j:
  69. r = paragraph.add_run(dataList[2].columns[j])
  70. r.font.bold = True
  71. r.font.size = Pt(10.5)
  72. r.font.name = 'Times New Roman'
  73. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  74. else:
  75. paragraph.add_run('')
  76. elif len(columnsList) > 3 and i > columnsList[2] and i < columnsList[3]:
  77. if len(dataList[2].columns) > j:
  78. r = paragraph.add_run(str(dataList[2].iloc[i - 13, j]))
  79. r.font.size = Pt(10.5)
  80. r.font.name = 'Times New Roman'
  81. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  82. else:
  83. paragraph.add_run('')
  84. elif i == columnsList[3]:
  85. # 第6*3行 显示前6个指 标的列名
  86. if len(dataList[3].columns) > j:
  87. r = paragraph.add_run(dataList[3].columns[j])
  88. r.font.bold = True
  89. r.font.size = Pt(10.5)
  90. r.font.name = 'Times New Roman'
  91. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  92. else:
  93. paragraph.add_run('')
  94. elif len(columnsList) > 4 and i > columnsList[3] and i < columnsList[4]:
  95. if len(dataList[3].columns) > j:
  96. r = paragraph.add_run(str(dataList[3].iloc[i - 19, j]))
  97. r.font.size = Pt(10.5)
  98. r.font.name = 'Times New Roman'
  99. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  100. else:
  101. paragraph.add_run('')
  102. elif i == columnsList[4]:
  103. # 第6*4行 显示前6个指 标的列名
  104. if len(dataList[4].columns) > j:
  105. r = paragraph.add_run(dataList[4].columns[j])
  106. r.font.bold = True
  107. r.font.size = Pt(10.5)
  108. r.font.name = 'Times New Roman'
  109. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  110. else:
  111. paragraph.add_run('')
  112. elif len(columnsList) > 5 and i > columnsList[4] and i < columnsList[5]:
  113. if len(dataList[4].columns) > j:
  114. r = paragraph.add_run(str(dataList[4].iloc[i - 25, j]))
  115. r.font.size = Pt(10.5)
  116. r.font.name = 'Times New Roman'
  117. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  118. else:
  119. paragraph.add_run('')
  120. elif i == columnsList[5]:
  121. # 第6*5行 显示前6个指 标的列名
  122. if len(dataList[5].columns) > j:
  123. r = paragraph.add_run(dataList[5].columns[j])
  124. r.font.bold = True
  125. r.font.size = Pt(10.5)
  126. r.font.name = 'Times New Roman'
  127. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  128. else:
  129. paragraph.add_run('')
  130. elif len(columnsList) > 6 and i > columnsList[5] and i < columnsList[6]:
  131. if len(dataList[5].columns) > j:
  132. r = paragraph.add_run(str(dataList[5].iloc[i - 31, j]))
  133. r.font.size = Pt(10.5)
  134. r.font.name = 'Times New Roman'
  135. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  136. else:
  137. paragraph.add_run('')
  138. elif i == columnsList[6]:
  139. # 第6*6行 显示前6个指 标的列名
  140. if len(dataList[6].columns) > j:
  141. r = paragraph.add_run(dataList[6].columns[j])
  142. r.font.bold = True
  143. r.font.size = Pt(10.5)
  144. r.font.name = 'Times New Roman'
  145. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  146. else:
  147. paragraph.add_run('')
  148. elif len(columnsList) > 7 and i > columnsList[6] and i < columnsList[7]:
  149. if len(dataList[6].columns) > j:
  150. r = paragraph.add_run(str(dataList[6].iloc[i - 37, j]))
  151. r.font.size = Pt(10.5)
  152. r.font.name = 'Times New Roman'
  153. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  154. else:
  155. paragraph.add_run('')
  156. elif i == columnsList[7]:
  157. # 第6*7行 显示前6个指 标的列名
  158. if len(dataList[7].columns) > j:
  159. r = paragraph.add_run(dataList[7].columns[j])
  160. r.font.bold = True
  161. r.font.size = Pt(10.5)
  162. r.font.name = 'Times New Roman'
  163. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  164. else:
  165. paragraph.add_run('')
  166. elif len(columnsList) >= 8 and i > columnsList[7] and i < columnsList[8]:
  167. if len(dataList[7].columns) > j:
  168. r = paragraph.add_run(str(dataList[7].iloc[i - 43, j]))
  169. r.font.size = Pt(10.5)
  170. r.font.name = 'Times New Roman'
  171. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  172. else:
  173. paragraph.add_run('')
  174. elif i == columnsList[8]:
  175. if len(dataList[8].columns) > j:
  176. # 第6*8行 显示前6个指 标的列名
  177. r = paragraph.add_run(dataList[8].columns[j])
  178. r.font.bold = True
  179. r.font.size = Pt(10.5)
  180. r.font.name = 'Times New Roman'
  181. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  182. else:
  183. paragraph.add_run('')
  184. elif len(columnsList) >= 9 and i > columnsList[8] and i < columnsList[9]:
  185. if len(dataList[8].columns) > j:
  186. r = paragraph.add_run(str(dataList[8].iloc[i - 49, j]))
  187. r.font.size = Pt(10.5)
  188. r.font.name = 'Times New Roman'
  189. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  190. else:
  191. paragraph.add_run('')
  192. elif i == columnsList[9]:
  193. # 第6*9行 显示前6个指 标的列名
  194. if len(dataList[9].columns) > j:
  195. r = paragraph.add_run(dataList[9].columns[j])
  196. r.font.bold = True
  197. r.font.size = Pt(10.5)
  198. r.font.name = 'Times New Roman'
  199. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  200. else:
  201. paragraph.add_run('')
  202. elif len(columnsList) > 10 and i > columnsList[9] and i <columnsList[10]:
  203. if len(dataList[9].columns) > j:
  204. r = paragraph.add_run(str(dataList[9].iloc[i - 55, j]))
  205. r.font.size = Pt(10.5)
  206. r.font.name = 'Times New Roman'
  207. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  208. else:
  209. paragraph.add_run('')
  210. elif i == columnsList[10]:
  211. # 第6*9行 显示前6个指 标的列名
  212. if len(dataList[10].columns) > j:
  213. r = paragraph.add_run(dataList[10].columns[j])
  214. r.font.bold = True
  215. r.font.size = Pt(10.5)
  216. r.font.name = 'Times New Roman'
  217. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  218. else:
  219. paragraph.add_run('')
  220. elif len(columnsList) > 11 and i > columnsList[10] and i < columnsList[11]:
  221. if len(dataList[10].columns) > j:
  222. r = paragraph.add_run(str(dataList[10].iloc[i - 61, j]))
  223. r.font.size = Pt(10.5)
  224. r.font.name = 'Times New Roman'
  225. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  226. else:
  227. paragraph.add_run('')
  228. elif i == columnsList[11]:
  229. # 第6*9行 显示前6个指 标的列名
  230. if len(dataList[11].columns) > j:
  231. r = paragraph.add_run(dataList[11].columns[j])
  232. r.font.bold = True
  233. r.font.size = Pt(10.5)
  234. r.font.name = 'Times New Roman'
  235. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  236. else:
  237. paragraph.add_run('')
  238. elif len(columnsList) > 12 and i > columnsList[11] and i < columnsList[12]:
  239. if len(dataList[11].columns) > j:
  240. r = paragraph.add_run(str(dataList[11].iloc[i - 67, j]))
  241. r.font.size = Pt(10.5)
  242. r.font.name = 'Times New Roman'
  243. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  244. else:
  245. paragraph.add_run('')
  246. elif i == columnsList[12]:
  247. print(i)
  248. # 第6*9行 显示前6个指 标的列名
  249. if len(dataList[12].columns) > j:
  250. r = paragraph.add_run(dataList[12].columns[j])
  251. r.font.bold = True
  252. r.font.size = Pt(10.5)
  253. r.font.name = 'Times New Roman'
  254. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  255. else:
  256. paragraph.add_run('')
  257. elif len(columnsList) >= 13 and i > columnsList[12] and i <= 77:
  258. print('last---',i)
  259. if len(dataList[12].columns) > j:
  260. r = paragraph.add_run(str(dataList[12].iloc[i - 73, j]))
  261. r.font.size = Pt(10.5)
  262. r.font.name = 'Times New Roman'
  263. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  264. else:
  265. paragraph.add_run('')
  266. paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  267. paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  268. paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  269. # 生成子报告: 物理指标 常规养分指标 一般化学性指标 重金属指标
  270. indexClassificationList = {
  271. '物理指标': ['pH', '土壤质地', '土壤容重1(g/cm³)', '土壤容重2(g/cm³)', '土壤容重3(g/cm³)', '土壤容重4(g/cm³)', '土壤容重平均值(g/cm³)',
  272. '2~0.2mm颗粒含量', '0.2~0.02mm颗粒含量', '0.02~0.002mm颗粒含量', '0.002mm以下颗粒含量', '水稳>5mm(%)', '水稳3mm~5mm(%)',
  273. '水稳2mm~3mm(%)', '水稳1mm~2mm(%)', '水稳0.5mm~1mm(%)', '水稳0.25mm~0.5mm(%)', '水稳性大团聚体总和(%)', '洗失量(吸管法需填)', '风干试样含水量(分析基)'],
  274. '常规养分指标': ['pH','有机质', '全氮', '全磷', '全钾', '有效磷', '速效钾', '有效硫', '有效硼', '有效铁', '有效锰', '有效铜', '有效锌', '有效钼', '有效硅', '缓效钾'],
  275. '一般化学性指标': ['pH','阳离子交换量', '交换性盐基总量', '交换性钙', '交换性镁', '交换性钠', '交换性钾', '全盐量', '电导率',
  276. '水溶性Na⁺含量', '水溶性K⁺含量', '水溶性Ca²⁺含量', '水溶性Mg²⁺含量', '水溶性Cl⁻含量', '水溶性CO₃²⁻含量','水溶性HCO₃⁻含量',
  277. '水溶性SO₄²⁻含量', '离子总量', '碳酸钙'],
  278. '重金属指标': ['pH', '总汞', '总砷', '总铅', '总镉', '总铬', '总镍']
  279. }
  280. # 生成物理指标审核报告
  281. def getphysicsReport(originData, data,type, changeFileUrl, saveFileUrl, check_1_data,
  282. check_3_data,
  283. check_5_data ,
  284. check_8_data, # 样品编号替换为编号
  285. check_10_data,
  286. check_12_data,
  287. check_14_data ):
  288. """
  289. :param type: 指标类型
  290. :param changeFileUrl: 选择的数据文件路径
  291. :param saveFileUrl: 保存的文件路径
  292. :param check_1_data: 土壤容重数据
  293. :param check_3_data: 水稳审核数据
  294. :param check_5_data: 盐离子数据
  295. :param check_8_data: 水溶性离子数据
  296. :param check_10_data: 有机质及氮磷钾数据
  297. :param check_12_data: 有效养分数据
  298. :param check_14_data: 重金属数据
  299. :return:
  300. """
  301. # 生成报告
  302. name = os.path.basename(changeFileUrl)
  303. n = name.split('.')
  304. areaName = n[0].replace('数据', '')
  305. # 生成一个新的文件夹用于存放审核报告相关的数据
  306. nowTime = time.strftime("%Y-%m-%d %H时%M分%S秒", time.localtime())
  307. dir_name = f'{areaName}-{type}数据审核报告'
  308. mkdir_path = saveFileUrl + '/' + dir_name + nowTime
  309. if not os.path.exists(mkdir_path):
  310. os.mkdir(mkdir_path)
  311. # 获取相应指标数据
  312. physicsData = data[indexClassificationList[type]]
  313. physicsDataNum = originData[indexClassificationList[type]]
  314. report.getFrequencyImage(physicsData, mkdir_path)
  315. physicsData['序号'] = data['序号']
  316. physicsData['原样品编号'] = data['原样品编号']
  317. physicsData['样品编号'] = data['样品编号']
  318. physicsData['地理位置'] = data['地理位置']
  319. physicsData['母质'] = data['母质']
  320. physicsData['土壤类型'] = data['土壤类型']
  321. physicsData['土地利用类型'] = data['土地利用类型']
  322. physicsData['土壤质地'] = data['土壤质地']
  323. # 生成相应审核报告
  324. # 根据选择的路径读取数据
  325. physicsData['原样品编号'] = physicsData['原样品编号'].astype(str)
  326. physicsDataNum['序号'] = originData['序号']
  327. physicsDataNum['原样品编号'] = originData['原样品编号']
  328. physicsDataNum['样品编号'] = originData['样品编号']
  329. physicsDataNum['地理位置'] = originData['地理位置']
  330. physicsDataNum['母质'] = originData['母质']
  331. physicsDataNum['土壤类型'] = originData['土壤类型']
  332. physicsDataNum['土地利用类型'] = originData['土地利用类型']
  333. physicsDataNum['土壤质地'] = originData['土壤质地']
  334. physicsDataNum['原样品编号'] = physicsDataNum['原样品编号'].astype(str)
  335. # todo 有数据后这里去掉注释
  336. # checkData = pd.read_excel(changeFileUrl, sheet_name='检测方法')
  337. # 上面这个地址,可以传递给函数中,用于保存表格和图片
  338. # 调用函数 开始生成报告相关内容
  339. # 表1相关数据
  340. typeData = report.getSimpleNum(physicsData)
  341. lenNum_1 = len(typeData['sData'])
  342. lenNum_1_f = len(typeData['allData'])
  343. table_1_data = pd.DataFrame({
  344. '类型': typeData['sData'].index,
  345. '数量': typeData['sData'],
  346. '合计': [typeData['sData'].sum() for _ in range(lenNum_1)]
  347. })
  348. # 表2数据
  349. table_2_data = report.getDataComplete(physicsData)
  350. table_2_data = table_2_data.reset_index()
  351. table_2_data.columns = ['指标名称', '实测数量', '应测数量']
  352. # 表3数据
  353. # table_3_data = report.checkMethod(checkData, mkdir_path)
  354. # 数据修约 表4
  355. report.getNum(physicsData, mkdir_path)
  356. # 数据填报项审核 表5
  357. report.dataReportResult(physicsData, mkdir_path)
  358. # 表6数据 土壤质地类型不一致
  359. # middData = physicsData[['原样品编号', '样品编号']].astype(str)
  360. # middData['编号'] = middData['原样品编号']
  361. # del middData['原样品编号']
  362. #
  363. # check_1_data = pd.merge(check_1_data, middData, how='left', on='编号')
  364. check_1_data = check_1_data.replace(np.nan, '')
  365. #typeNotSame = check_1_data[check_1_data['土壤质地'] != check_1_data['土壤质地(判断)']]
  366. #table_6_data = typeNotSame[['编号', '样品编号', '土壤质地', '土壤质地(判断)']]
  367. allNeedData = pd.DataFrame({})
  368. allNeedData['原样品编号'] = check_1_data['编号']
  369. getSimpleDataNumber = pd.merge(allNeedData, physicsData[['原样品编号', '样品编号']], how='left', on="原样品编号")
  370. allNeedData['样品编号'] = getSimpleDataNumber['样品编号']
  371. allNeedData['土地利用类型'] = check_1_data['土地利用类型']
  372. allNeedData['审核结果'] = check_1_data['审核结果'] + check_3_data['审核结果']
  373. allNeedData['外业'] = ['' for _ in range(len(check_1_data))]
  374. table_7_data = allNeedData[allNeedData['审核结果'] != '']
  375. del table_7_data['审核结果']
  376. # 写进表格
  377. with pd.ExcelWriter(f'{mkdir_path}/超阈值样品统计表.xlsx', engine='openpyxl') as writer:
  378. table_7_data.to_excel(writer, index=False, sheet_name='超阈值数据')
  379. # 表8数据
  380. table_8_data = report.getPHData(physicsData, mkdir_path)
  381. # 表13 所有存疑数据
  382. with pd.ExcelWriter(f'{mkdir_path}/数据审核过程存疑数据一览表.xlsx', engine='openpyxl') as writer:
  383. allNeedData[allNeedData['审核结果'] != ''].to_excel(writer, index=False, sheet_name='存疑数据')
  384. # 附表: 频度分析图
  385. # report.getFrequencyImage(physicsData, mkdir_path)
  386. table_f_2_data = report.getFrequencyInformation(data, mkdir_path)
  387. # 新建一个文档
  388. doc = Document()
  389. # 添加标题
  390. doc.add_heading(f"{areaName}第三次全国土壤普查物理指标检测数据审核报告", level=0)
  391. # 在文档中添加封面段落
  392. fm = doc.add_paragraph()
  393. fm = doc.add_paragraph()
  394. fm = doc.add_paragraph()
  395. fm = doc.add_paragraph()
  396. fm = doc.add_paragraph()
  397. # 插入图片,设置宽度为6英寸(可根据需求调整)
  398. run = fm.add_run()
  399. run.add_picture('img/第三次全国土壤普查img.png', width=Inches(2.26))
  400. fm.alignment = WD_TABLE_ALIGNMENT.CENTER
  401. # 在文档中添加封面段落
  402. fm = doc.add_paragraph()
  403. fm = doc.add_paragraph()
  404. fm = doc.add_paragraph()
  405. fm = doc.add_paragraph()
  406. fm = doc.add_paragraph()
  407. fm = doc.add_paragraph()
  408. # 获取当前日期
  409. current_date = datetime.now()
  410. # 将年份和月份转换为中文大写数字
  411. year = int(current_date.strftime("%Y")) # 转换为整数
  412. month = int(current_date.strftime("%m")) # 转换为整数
  413. # 使用 cn2an 将数字转换为中文大写
  414. year_chinese = number_to_chinese_year(year) # 年份转换
  415. month_chinese = cn2an.an2cn(month) # 月份转换
  416. current_date_formatted = f"{year_chinese}年{month_chinese}月"
  417. # 组合动态文本
  418. dynamic_text = f"安徽农业大学资源与环境学院\n{current_date_formatted}"
  419. # 添加文字并居中
  420. text_paragraph = doc.add_paragraph()
  421. text_run = text_paragraph.add_run(dynamic_text)
  422. text_run.font.name = "宋体"
  423. text_run.font.size = Pt(18)
  424. text_run.bold = True # 设置字体加粗
  425. text_paragraph.alignment = 1 # 1 表示居中对齐
  426. # TODO 添加目录
  427. # 正确插入分页符
  428. doc.add_page_break()
  429. heading = doc.add_heading('总体概述', level=1)
  430. heading.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  431. # 第一段
  432. long_text1 = f"""
  433. {areaName}第三次全国土壤普查县级数据审核报告主要通过收集和整理相关数据,并对其进行内业检测数据的完整性、规范性和合理性进行审核,形成存疑样点清单及存疑样点结果判定,最终编制完成数据审核报告,同时提交( )对相关指标进行整改复测。报告整理了( )个表层样品数据(含平行样、质控样)、( )个水稳性大团聚体样品数据(含平行样)、( )个剖面样品数据(含平行样、质控样),共( )次样品检测结果分析情况。相关结果分别按照物理性指标检测数据、一般化学指标检测数据、常规养分指标检测数据和重金属指标检测数据形成四份报告。本报告为表层样常规养分指标检测数据审核报告。
  434. """
  435. para0 = doc.add_paragraph(long_text1)
  436. run0 = para0.runs[0] # 获取段落中的第一个run对象
  437. run0.font.name = '宋体' # 设置字体为宋体
  438. run0.font.size = Pt(11) # 设置字号为11磅
  439. # 设置段落的行间距为1.5倍
  440. para_format = para0.paragraph_format
  441. para_format.line_spacing = 1.5 # 设置行间距为1.5倍
  442. # 添加一级标题
  443. doc.add_heading('一、数据完整性审核', level=1)
  444. # 第二段
  445. long_text2 = """
  446. 外业信息调查采样环节:采用电子围栏和外业调查采样APP,对采样位置和填报信息进行管理,确保外业调查信息填报完整。
  447. 样品检测数据上报环节:通过土壤普查工作平台对上报数据的完整性进行筛查。( )第三次土壤普查相关指标检测数据由( )提供,数据均已通过省级质控实验室和县级土壤普查办审核;相关土壤指标历史数据则由( )第三次土壤普查办公室提供。根据《第三次全国土壤普查土壤样品制备与检测技术规范(修订版)》要求,统计各土地利用类型的样品数量,并按照耕地园地土壤样品(表层/剖面)、林地草地土壤样品(表层/剖面)以及水稳定性大团聚体样品(见表1)进行分类,编制了指标名称与实际检测样品数量统计表(见表2),其中水溶性盐分总量大于(),增加检测了八大离子(该指标在化学指标检测数据审核报告内)。
  448. """
  449. para = doc.add_paragraph(long_text2)
  450. run1 = para.runs[0]
  451. run1.font.name = '宋体' # 设置字体为宋体
  452. run1.font.size = Pt(11) # 设置字号为11磅
  453. # 设置段落的行间距为1.5倍
  454. para_format = para.paragraph_format
  455. para_format.line_spacing = 1.5 # 设置行间距为1.5倍
  456. doc.add_heading('1、土地利用类型与检测指标符合性审核', level=2)
  457. # 插入表格1
  458. paragraph_1 = doc.add_paragraph()
  459. paragraph_1.add_run(f"表1:{areaName}三普样品数量统计表(表层)").bold = True
  460. # 设置居中
  461. paragraph_1.alignment = WD_ALIGN_PARAGRAPH.CENTER
  462. table_1 = doc.add_table(rows=lenNum_1 + 1, cols=3, style='Light Shading Accent 1')
  463. table_1.alignment = WD_TABLE_ALIGNMENT.CENTER
  464. # 遍历表格 插入数据
  465. # 遍历表格的所有单元格,并填充内容
  466. for i, row in enumerate(table_1.rows):
  467. for j, cell in enumerate(row.cells):
  468. # 获取单元格中的段落对象
  469. paragraph = cell.paragraphs[0]
  470. if i == 0:
  471. r = paragraph.add_run(str(table_1_data.columns[j]))
  472. r.font.bold = True
  473. else:
  474. r = paragraph.add_run(str(table_1_data.iloc[i - 1, j]))
  475. r.font.size = Pt(10.5)
  476. r.font.name = 'Times New Roman'
  477. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  478. paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  479. paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  480. paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  481. # 合并单元格 合并第3列的第二行和第三行
  482. if lenNum_1 > 1:
  483. table_1.cell(2, 2).text = ''
  484. table_1.cell(1, 2).merge(table_1.cell(2, 2))
  485. ############test##############
  486. doc.add_heading('2、指标名称与实际检测样品数量完整性审核', level=2)
  487. # 插入表格2
  488. paragraph_2 = doc.add_paragraph()
  489. paragraph_2.add_run(f'表2:{areaName}指标名称与实际检测样品数量统计表').bold = True
  490. table_2 = doc.add_table(rows=len(table_2_data) + 1, cols=3, style='Light Shading Accent 1')
  491. paragraph_2.alignment = WD_ALIGN_PARAGRAPH.CENTER
  492. table_2.alignment = WD_TABLE_ALIGNMENT.CENTER
  493. for i, row in enumerate(table_2.rows):
  494. for j, cell in enumerate(row.cells):
  495. # 获取单元格中的段落对象
  496. paragraph = cell.paragraphs[0]
  497. if i == 0:
  498. r = paragraph.add_run(str(table_2_data.columns[j]))
  499. r.font.bold = True
  500. else:
  501. r = paragraph.add_run(str(table_2_data.iloc[i - 1, j]))
  502. paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  503. paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  504. paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  505. r.font.size = Pt(10.5)
  506. r.font.name = 'Times New Roman'
  507. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  508. doc.add_heading('二、数据规范性审核', level=1)
  509. long_text3 = """
  510. 按照《第三次全国土壤普查暂行土壤分类系统 (试行)》、《第三次全国土壤普查工作底图制作与采样点布设技术规范》、《第三次全国土壤普查土壤类型图编制技术规范》《第三次全国土壤普查土壤样品制备与检测技术规范》等规范统一标准和表现形式,土地利用方式按照第三次国土调查土地利用信息统一,种植制度按照农业区划信息进行统一。三普工作平台同时内置指标量纲、数字修约和允差等,控制数据规范性。
  511. 根据《第三次全国土壤普查土壤样品制备与检测技术规范(修订版)》,对检测指标对应的检测方法与相关标准或规范进行审核,得到检测方法审核、数值修约审核、数据填报项审核结果,未检出项填报以检出限的一半上报并加注*号。根据土壤普查教材中机械组成分类参考表,并进行宁国土壤质地填报审核结果表(见表6)。
  512. """
  513. para = doc.add_paragraph(long_text3)
  514. run1 = para.runs[0]
  515. run1.font.name = '宋体' # 设置字体为宋体
  516. run1.font.size = Pt(11) # 设置字号为11磅
  517. # 设置段落的行间距为1.5倍
  518. para_format = para.paragraph_format
  519. para_format.line_spacing = 1.5 # 设置行间距为1.5倍
  520. doc.add_heading('1、数据填报规范性审核', level=2)
  521. # 插入表3
  522. paragraph_3 = doc.add_paragraph()
  523. paragraph_3.add_run(f'表3:{areaName}土壤检测数据检测方法填报审核结果表').bold = True
  524. # table_3 = doc.add_table(rows=2, cols=2)
  525. paragraph_3.alignment = WD_ALIGN_PARAGRAPH.CENTER
  526. # table_3.alignment = WD_TABLE_ALIGNMENT.CENTER
  527. # 写入数据 这里数据写不下 嵌入链接
  528. doc.add_heading('为避免数据量过多无法显示,请至数据保存文件夹中查看数据表:检测方法审核结果.xlsx', level=4)
  529. doc.add_heading('2、数值修约规范性审核', level=2)
  530. # 插入表4
  531. paragraph_4 = doc.add_paragraph()
  532. paragraph_4.add_run(f'表4:{areaName}土壤检测数据数值修约结果表').bold = True
  533. # table_4 = doc.add_table(rows=2, cols=2)
  534. paragraph_4.alignment = WD_ALIGN_PARAGRAPH.CENTER
  535. # table_4.alignment = WD_TABLE_ALIGNMENT.CENTER
  536. doc.add_heading('为避免数据量过多无法显示,请至数据保存文件夹中查看数据表:数值修约审核.xlsx', level=4)
  537. # 填入数据 这里数据也放不下 嵌入链接
  538. doc.add_heading('3、数据未检出的填报规范性审核', level=2)
  539. # 插入表5
  540. paragraph_5 = doc.add_paragraph()
  541. paragraph_5.add_run(f'表5:{areaName}土壤检测数据未检出项填报审核结果表').bold = True
  542. # table_5 = doc.add_table(rows=2, cols=2)
  543. paragraph_5.alignment = WD_ALIGN_PARAGRAPH.CENTER
  544. # table_5.alignment = WD_TABLE_ALIGNMENT.CENTER
  545. # 写入数据 这里数据也放不下 嵌入链接
  546. doc.add_heading('为避免数据量过多无法显示,请至数据保存文件夹中查看数据表:数据填报项审核结果.xlsx', level=4)
  547. doc.add_heading('4、土壤质地填报规范性审核', level=2)
  548. # 插入表6
  549. # paragraph_6 = doc.add_paragraph()
  550. # paragraph_6.add_run(f'表6:{areaName}土壤质地填报审核结果表').bold = True
  551. # table_6 = doc.add_table(rows=len(table_6_data) + 1, cols=4, style='Light Shading Accent 1')
  552. # paragraph_6.alignment = WD_ALIGN_PARAGRAPH.CENTER
  553. # table_6.alignment = WD_TABLE_ALIGNMENT.CENTER
  554. # 提取结果表中数据
  555. # 写入数据 土壤质地类型不一致的数据提取出来
  556. # for i, row in enumerate(table_6.rows):
  557. # for j, cell in enumerate(row.cells):
  558. # # 获取单元格中的段落对象
  559. # paragraph = cell.paragraphs[0]
  560. # if i == 0:
  561. # r = paragraph.add_run(str(table_6_data.columns[j]))
  562. # r.font.bold = True
  563. # else:
  564. # r = paragraph.add_run(str(table_6_data.iloc[i - 1, j]))
  565. # paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  566. # paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  567. # paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  568. # r.font.size = Pt(10.5)
  569. # r.font.name = 'Times New Roman'
  570. # r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  571. doc.add_heading('三、数据合理性审核', level=1)
  572. long_text4 = """
  573. 明确数据审核原则,结合外业调查采样,获取的成土环境、土壤利用现状等信息对结果进行综合评价。通过阈值分析、关联分析、逻辑分析等方法对数据准确性进行判断。
  574. 阈值法(国家和省级数据阈值):结合区域历史数据建立阈值,平台利用阈值法(国家和省级数据值)自动对检测数据进行初步审核,并对超出阈值范围数据做出警示标识,专家或专业技术人员结合区域实际、专家经验判定异常值并对异常数据进行驳回。超出阈值颜色标注。
  575. 红色: 超出国家阈值,维持试点期间的标红。
  576. 黄色: 省级阈值在国家阈值范围内的,数据超出省级阈值标黄。
  577. 紫色: 省级阈值超出国家阈值的,数据超出省级阈值标成紫色(注,此种情况超国家阈值的红色服从紫色,仅标紫色)
  578. 极值法: 常用的统计量是均值、标准差、最大值、最小值、分位数等,用来判断是否超出了合理的极值范围。根据相关指标历年数据与指标最大值、最小值、平均数、中位数和极差进行审查,结合相关外业情况。
  579. 关联分析方法: 存在量化关系的指标,通过设定组合筛选异常值,如碳氮比等关联分析。
  580. 指标综合分析:根据指标相互之间的关系,如有效磷在全磷中的占比、全钾与速效钾缓效钾之和的关系等。有机质、全磷、有效磷、全钾等数据异常; 全氮和有机质之间关系不合理; 速效钾含量远大于缓效钾,盐基总量远大于阳离子交换量; 部分样品阳离子交换量和交换性盐基总量测定结果偏低; 水溶盐离子总量与全盐量的相对偏差已远超过方法规定的允差范围; 容重检测偏差比较大;水稳性大团聚体土壤干燥结块,影响测定结果、重金属按照风险筛选值和风险管控值等问题。
  581. 数据质量溯源:异常数据溯源,可能是内业测试化验环节问题,也有可能是外业调查采样问题,要结合数据检测和异常复检情况具体判断。
  582. """
  583. para = doc.add_paragraph(long_text4)
  584. run1 = para.runs[0]
  585. run1.font.name = '宋体' # 设置字体为宋体
  586. run1.font.size = Pt(11) # 设置字号为11磅
  587. doc.add_heading('1、阈值法审核', level=2)
  588. # 插入表格
  589. paragraph_7 = doc.add_paragraph()
  590. paragraph_7.add_run(f'表7:{areaName}土壤检测数据超阈值样品统计表').bold = True
  591. # table_7 = doc.add_table(rows=2, cols=2)
  592. # paragraph_7.alignment = WD_ALIGN_PARAGRAPH.CENTER
  593. # table_7.alignment = WD_TABLE_ALIGNMENT.CENTER
  594. # 写入数据 点击查看数据 这里也不一定写的下 最好是嵌入链接
  595. doc.add_heading('为避免数据量过多无法显示,请至数据保存文件夹中查看数据表:超阈值样品统计表.xlsx', level=4)
  596. # todo 合并所有数据 审核结果不为空的数据 写入表格保存到指定文件夹
  597. doc.add_heading('2、极值法审核', level=2)
  598. doc.add_heading('(1)pH', level=3)
  599. # 插入ph分布图
  600. if os.path.isfile(f'{mkdir_path}/PH值分布图.png'):
  601. doc.add_picture(f'{mkdir_path}/PH值分布图.png', width=Inches(6.0))
  602. paragraph_t_1 = doc.add_paragraph()
  603. paragraph_t_1.add_run(f'图1:pH值分布情况').bold = True
  604. paragraph_t_1.alignment = WD_ALIGN_PARAGRAPH.CENTER
  605. # 插入频度统计表
  606. paragraph_8 = doc.add_paragraph()
  607. paragraph_8.add_run('表8:pH数据统计表').bold = True
  608. table_8 = doc.add_table(rows=6, cols=2, style='Light Shading Accent 1')
  609. t_8 = table_8_data['频度分析']
  610. t_8 = t_8.reset_index()
  611. t_8.columns = ['指标', '数据']
  612. paragraph_8.alignment = WD_ALIGN_PARAGRAPH.CENTER
  613. table_8.alignment = WD_TABLE_ALIGNMENT.CENTER
  614. for i, row in enumerate(table_8.rows):
  615. for j, cell in enumerate(row.cells):
  616. # 获取单元格中的段落对象
  617. paragraph = cell.paragraphs[0]
  618. if i == 0:
  619. r = paragraph.add_run(str(t_8.columns[j]))
  620. r.font.bold = True
  621. else:
  622. r = paragraph.add_run(str(t_8.iloc[i - 1, j]))
  623. r.font.size = Pt(10.5)
  624. r.font.name = 'Times New Roman'
  625. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  626. paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  627. paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  628. paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  629. # 插入异常数据提取表格 todo 这里数据多的话也可能写不下 最好是嵌入一下
  630. if not table_8_data['异常数据'].empty:
  631. paragraph_9 = doc.add_paragraph()
  632. paragraph_9.add_run('表9:pH异常数据统计表').bold = True
  633. table_9 = doc.add_table(rows=len(table_8_data['异常数据']) + 1, cols=6, style='Light Shading Accent 1')
  634. t_9 = table_8_data['异常数据']
  635. paragraph_9.alignment = WD_ALIGN_PARAGRAPH.CENTER
  636. table_9.alignment = WD_TABLE_ALIGNMENT.CENTER
  637. for i, row in enumerate(table_9.rows):
  638. for j, cell in enumerate(row.cells):
  639. # 获取单元格中的段落对象
  640. paragraph = cell.paragraphs[0]
  641. if i == 0:
  642. r = paragraph.add_run(str(t_9.columns[j]))
  643. r.font.bold = True
  644. else:
  645. r = paragraph.add_run(str(t_9.iloc[i - 1, j]))
  646. r.font.size = Pt(10.5)
  647. r.font.name = 'Times New Roman'
  648. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  649. paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  650. paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  651. paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  652. doc.add_heading('四、审核存疑数据', level=1)
  653. paragraph_12 = doc.add_paragraph()
  654. paragraph_12.add_run(f'表10:数据审核过程存疑数据一览表').bold = True
  655. paragraph_12.alignment = WD_ALIGN_PARAGRAPH.CENTER
  656. doc.add_heading('为避免数据量过多无法显示,请至数据保存文件夹中查看数据表:物理指标数据审核过程存疑数据一览表.xlsx', level=4)
  657. doc.add_heading('五、附表', level=1)
  658. doc.add_heading('附表1:某区三普样品数量统计表(表层)', level=2)
  659. # 插入附表1
  660. table_1_f = doc.add_table(rows=lenNum_1 + 1, cols=3, style='Light Shading Accent 1')
  661. table_1_f.alignment = WD_TABLE_ALIGNMENT.CENTER
  662. # 遍历表格 插入数据
  663. # 遍历表格的所有单元格,并填充内容
  664. for i, row in enumerate(table_1_f.rows):
  665. for j, cell in enumerate(row.cells):
  666. # 获取单元格中的段落对象
  667. paragraph = cell.paragraphs[0]
  668. if i == 0:
  669. r = paragraph.add_run(str(table_1_data.columns[j]))
  670. r.font.bold = True
  671. else:
  672. r = paragraph.add_run(str(table_1_data.iloc[i - 1, j]))
  673. r.font.size = Pt(10.5)
  674. r.font.name = 'Times New Roman'
  675. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  676. paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  677. paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  678. paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  679. # 合并单元格 合并第3列的第二行和第三行
  680. if lenNum_1 > 1:
  681. table_1_f.cell(2, 2).text = ''
  682. table_1_f.cell(1, 2).merge(table_1_f.cell(2, 2))
  683. doc.add_heading('附表2:各指标频度分析表', level=2)
  684. # 插入表格 写入数据
  685. table_f_2_data = table_f_2_data.replace(np.nan, '')
  686. makeInfoTable(table_f_2_data, doc)
  687. # table_f_2 = doc.add_table(rows=len(table_f_2_data) + 1, cols=6, style='Light Shading Accent 1')
  688. # for i, row in enumerate(table_f_2.rows):
  689. # for j, cell in enumerate(row.cells):
  690. # # 获取单元格中的段落对象
  691. # paragraph = cell.paragraphs[0]
  692. # if i == 0:
  693. # r = paragraph.add_run(str(table_f_2_data.columns[j]))
  694. # r.font.bold = True
  695. # else:
  696. # r = paragraph.add_run(str(table_f_2_data.iloc[i - 1, j]))
  697. # r.font.size = Pt(10.5)
  698. # r.font.name = 'Times New Roman'
  699. # r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  700. # paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  701. # paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  702. # paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  703. # doc.add_heading('为避免数据量过多无法显示,请至数据保存文件夹中查看数据表:频度分析表.xlsx', level=4)
  704. doc.add_heading('附表3:各指标频度分析图', level=2)
  705. # 插入频度信息的图形
  706. if os.path.isfile(f'{mkdir_path}/0.002mm以下颗粒含量分析图.png'):
  707. doc.add_picture(f'{mkdir_path}/0.002mm以下颗粒含量分析图.png', width=Inches(6.0))
  708. if os.path.isfile(f'{mkdir_path}/0.02~0.002mm颗粒含量分析图.png.png'):
  709. doc.add_picture(f'{mkdir_path}/0.02~0.002mm颗粒含量分析图.png', width=Inches(6.0))
  710. if os.path.isfile(f'{mkdir_path}/0.2~0.02mm颗粒含量分析图.png'):
  711. doc.add_picture(f'{mkdir_path}/0.2~0.02mm颗粒含量分析图.png', width=Inches(6.0))
  712. if os.path.isfile(f'{mkdir_path}/2~0.2mm颗粒含量分析图.png'):
  713. doc.add_picture(f'{mkdir_path}/2~0.2mm颗粒含量分析图.png', width=Inches(6.0))
  714. if os.path.isfile(f'{mkdir_path}/pH分析图.png'):
  715. doc.add_picture(f'{mkdir_path}/pH分析图.png', width=Inches(6.0))
  716. if os.path.isfile(f'{mkdir_path}/风干试样含水量(分析基)分析图.png'):
  717. doc.add_picture(f'{mkdir_path}/风干试样含水量(分析基)分析图.png', width=Inches(6.0))
  718. if os.path.isfile(f'{mkdir_path}/洗失量(吸管法需填)分析图.png'):
  719. doc.add_picture(f'{mkdir_path}/洗失量(吸管法需填)分析图.png', width=Inches(6.0))
  720. if os.path.isfile(f'{mkdir_path}/土壤容重1分析图.png'):
  721. doc.add_picture(f'{mkdir_path}/土壤容重1分析图.png', width=Inches(6.0))
  722. if os.path.isfile(f'{mkdir_path}/土壤容重2分析图.png'):
  723. doc.add_picture(f'{mkdir_path}/土壤容重2分析图.png', width=Inches(6.0))
  724. if os.path.isfile(f'{mkdir_path}/土壤容重3分析图.png'):
  725. doc.add_picture(f'{mkdir_path}/土壤容重3分析图.png', width=Inches(6.0))
  726. if os.path.isfile(f'{mkdir_path}/土壤容重4分析图.png'):
  727. doc.add_picture(f'{mkdir_path}/土壤容重4分析图.png', width=Inches(6.0))
  728. if os.path.isfile(f'{mkdir_path}/土壤容重平均值分析图.png'):
  729. doc.add_picture(f'{mkdir_path}/土壤容重平均值分析图.png', width=Inches(6.0))
  730. if os.path.isfile(f'{mkdir_path}/水稳0.5mm~1mm分析图.png'):
  731. doc.add_picture(f'{mkdir_path}/水稳0.5mm~1mm分析图.png', width=Inches(6.0))
  732. if os.path.isfile(f'{mkdir_path}/水稳0.25mm~0.5mm分析图.png'):
  733. doc.add_picture(f'{mkdir_path}/水稳0.25mm~0.5mm分析图.png', width=Inches(6.0))
  734. if os.path.isfile(f'{mkdir_path}/水稳1mm~2mm分析图.png'):
  735. doc.add_picture(f'{mkdir_path}/水稳1mm~2mm分析图.png', width=Inches(6.0))
  736. if os.path.isfile(f'{mkdir_path}/水稳2mm~3mm分析图.png'):
  737. doc.add_picture(f'{mkdir_path}/水稳2mm~3mm分析图.png', width=Inches(6.0))
  738. if os.path.isfile(f'{mkdir_path}/水稳3mm~5mm分析图.png'):
  739. doc.add_picture(f'{mkdir_path}/水稳3mm~5mm分析图.png', width=Inches(6.0))
  740. if os.path.isfile(f'{mkdir_path}/水稳5mm分析图.png'):
  741. doc.add_picture(f'{mkdir_path}/水稳5mm分析图.png', width=Inches(6.0))
  742. doc.add_heading('附表4:数值修约标准', level=2)
  743. # 读取数据 插入表格 写入数据
  744. numData = pd.read_excel('./img/数值修约要求.xlsx', sheet_name='Sheet1')
  745. table_2_f = doc.add_table(rows=len(numData) + 1, cols=2, style='Light Shading Accent 1')
  746. table_2_f.alignment = WD_TABLE_ALIGNMENT.CENTER
  747. for i, row in enumerate(table_2_f.rows):
  748. for j, cell in enumerate(row.cells):
  749. # 获取单元格中的段落对象
  750. paragraph = cell.paragraphs[0]
  751. if i == 0:
  752. r = paragraph.add_run(str(numData.columns[j]))
  753. r.font.bold = True
  754. else:
  755. r = paragraph.add_run(str(numData.iloc[i - 1, j]))
  756. r.font.size = Pt(10.5)
  757. r.font.name = 'Times New Roman'
  758. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  759. paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  760. paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  761. paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  762. # 处理样式 遍历所有的段落 修改字体
  763. # 遍历并打印每个段落的文本
  764. paragraphs = doc.paragraphs
  765. for paragraph in paragraphs:
  766. for run in paragraph.runs:
  767. run.font.color.rgb = RGBColor(0, 0, 0)
  768. run.font.name = 'Times New Roman'
  769. run.font.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  770. # 保存Word文档
  771. # doc.add_page_break()
  772. # dir = doc.add_heading('目录')
  773. # dir.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  774. # dir.style.font.size = Pt(20)
  775. # headings_info = []
  776. # for para in doc.paragraphs:
  777. # if para.style.name.startswith("Heading"):
  778. # level = int(para.style.name[len("Heading"):])
  779. # text = para.text
  780. # headings_info.append((text, level))
  781. # for headings in headings_info:
  782. # if headings[1] < 3:
  783. # if headings[1] == 1 and headings[0] != '目录':
  784. # first_level = doc.add_heading(headings[0])
  785. # first_level.style.font.size = Pt(12)
  786. # first_level.paragraph_format.line_spacing = 0.5
  787. # elif headings[1] == 2:
  788. # second_level = doc.add_heading(' '+headings[0])
  789. # second_level.style.font.size = Pt(12)
  790. # second_level.paragraph_format.line_spacing = 0.5
  791. doc.save(f'{mkdir_path}/{areaName}-{type}审核报告.docx')
  792. # 生成常规养分指标审核报告
  793. def getConventionalNutrientIndicators(originData, data,type, changeFileUrl, saveFileUrl, check_1_data,
  794. check_3_data,
  795. check_5_data,
  796. check_8_data, # 样品编号替换为编号
  797. check_10_data,
  798. check_12_data,
  799. check_14_data ):
  800. # 生成报告
  801. name = os.path.basename(changeFileUrl)
  802. n = name.split('.')
  803. areaName = n[0].replace('数据', '')
  804. # 生成一个新的文件夹用于存放审核报告相关的数据
  805. nowTime = time.strftime("%Y-%m-%d %H时%M分%S秒", time.localtime())
  806. dir_name = f'{areaName}-{type}数据审核报告'
  807. mkdir_path = saveFileUrl + '/' + dir_name + nowTime
  808. if not os.path.exists(mkdir_path):
  809. os.mkdir(mkdir_path)
  810. # 根据选择的路径读取数据
  811. ConventionalNutrientData = data[indexClassificationList[type]]
  812. ConventionalNutrientDataNum = originData[indexClassificationList[type]]
  813. report.getFrequencyImage(ConventionalNutrientData, mkdir_path)
  814. ConventionalNutrientData['序号'] = data['序号']
  815. ConventionalNutrientData['原样品编号'] = data['原样品编号']
  816. ConventionalNutrientData['样品编号'] = data['样品编号']
  817. ConventionalNutrientData['地理位置'] = data['地理位置']
  818. ConventionalNutrientData['母质'] = data['母质']
  819. ConventionalNutrientData['土壤类型'] = data['土壤类型']
  820. ConventionalNutrientData['土地利用类型'] = data['土地利用类型']
  821. # ConventionalNutrientData['土壤质地'] = data['土壤质地']
  822. # 生成相应审核报告
  823. ConventionalNutrientData['原样品编号'] = ConventionalNutrientData['原样品编号'].astype(str)
  824. ConventionalNutrientDataNum['序号'] = originData['序号']
  825. ConventionalNutrientDataNum['原样品编号'] = originData['原样品编号']
  826. ConventionalNutrientDataNum['样品编号'] = originData['样品编号']
  827. ConventionalNutrientDataNum['地理位置'] = originData['地理位置']
  828. ConventionalNutrientDataNum['母质'] = originData['母质']
  829. ConventionalNutrientDataNum['土壤类型'] = originData['土壤类型']
  830. ConventionalNutrientDataNum['土地利用类型'] = originData['土地利用类型']
  831. data['原样品编号'] = data['原样品编号'].astype(str)
  832. # checkData = pd.read_excel(changeFileUrl, sheet_name='检测方法')
  833. # 上面这个地址,可以纯递给函数中,用于保存表格和图片
  834. # 调用函数 开始生成报告相关内容
  835. # 表1相关数据
  836. typeData = report.getSimpleNum(ConventionalNutrientData)
  837. lenNum_1 = len(typeData['sData'])
  838. lenNum_1_f = len(typeData['allData'])
  839. table_1_data = pd.DataFrame({
  840. '类型': typeData['sData'].index,
  841. '数量': typeData['sData'],
  842. '合计': [typeData['sData'].sum() for _ in range(lenNum_1)]
  843. })
  844. # 表2数据
  845. table_2_data = report.getDataComplete(ConventionalNutrientData)
  846. table_2_data = table_2_data.reset_index()
  847. table_2_data.columns = ['指标名称', '实测数量', '应测数量']
  848. # 表3数据
  849. # table_3_data = report.checkMethod(checkData, mkdir_path)
  850. # 数据修约 表4
  851. report.getNum(ConventionalNutrientDataNum, mkdir_path)
  852. # 数据填报项审核 表5
  853. report.dataReportResult(ConventionalNutrientData, mkdir_path)
  854. # 表6数据 土壤质地类型不一致
  855. middData = data[['原样品编号', '样品编号']].astype(str)
  856. middData['编号'] = middData['原样品编号']
  857. del middData['原样品编号']
  858. check_1_data = pd.merge(check_1_data, middData, how='left', on='编号')
  859. check_1_data = check_1_data.replace(np.nan, '')
  860. # typeNotSame = check_1_data[check_1_data['土壤质地'] != check_1_data['土壤类型(判断)']]
  861. # table_6_data = typeNotSame[['编号', '样品编号', '土壤质地', '土壤类型(判断)']]
  862. allNeedData = pd.DataFrame({})
  863. allNeedData['原样品编号'] = check_1_data['编号']
  864. getSimpleDataNumber = pd.merge(allNeedData, ConventionalNutrientData[['原样品编号', '样品编号']], how='left', on="原样品编号")
  865. allNeedData['样品编号'] = getSimpleDataNumber['样品编号']
  866. allNeedData['土地利用类型'] = check_1_data['土地利用类型']
  867. allNeedData['审核结果'] = check_10_data['审核结果'] + check_12_data['审核结果']
  868. allNeedData['外业'] = ['' for _ in range(len(check_1_data))]
  869. table_7_data = allNeedData[allNeedData['审核结果'] != '']
  870. del table_7_data['审核结果']
  871. # 写进表格
  872. with pd.ExcelWriter(f'{mkdir_path}/超阈值样品统计表.xlsx', engine='openpyxl') as writer:
  873. table_7_data.to_excel(writer, index=False, sheet_name='超阈值数据')
  874. # 表8数据
  875. table_8_data = report.getPHData(ConventionalNutrientData, mkdir_path)
  876. # 表10 数据
  877. table_10_data = report.getNAndC(ConventionalNutrientData, mkdir_path)
  878. # 表11 数据:全磷和有效磷异常数据统计
  879. table_11_data = report.getPData(ConventionalNutrientData, mkdir_path)
  880. report.getKData(ConventionalNutrientData, mkdir_path)
  881. # 表13 所有存疑数据
  882. with pd.ExcelWriter(f'{mkdir_path}/数据审核过程存疑数据一览表.xlsx', engine='openpyxl') as writer:
  883. allNeedData[allNeedData['审核结果'] != ''].to_excel(writer, index=False, sheet_name='存疑数据')
  884. # 附表: 频度分析图
  885. # report.getFrequencyImage(ConventionalNutrientData, mkdir_path)
  886. table_f_2_data = report.getFrequencyInformation(data, mkdir_path)
  887. # 新建一个文档
  888. doc = Document()
  889. # 添加标题
  890. doc.add_heading(f"{areaName}第三次全国土壤普查常规养分指标检测数据审核报告", level=0)
  891. # 在文档中添加封面段落
  892. fm = doc.add_paragraph()
  893. fm = doc.add_paragraph()
  894. fm = doc.add_paragraph()
  895. fm = doc.add_paragraph()
  896. fm = doc.add_paragraph()
  897. # 插入图片,设置宽度为6英寸(可根据需求调整)
  898. run = fm.add_run()
  899. run.add_picture('img/第三次全国土壤普查img.png', width=Inches(2.26))
  900. fm.alignment = WD_TABLE_ALIGNMENT.CENTER
  901. # 在文档中添加封面段落
  902. fm = doc.add_paragraph()
  903. fm = doc.add_paragraph()
  904. fm = doc.add_paragraph()
  905. fm = doc.add_paragraph()
  906. fm = doc.add_paragraph()
  907. fm = doc.add_paragraph()
  908. # 获取当前日期
  909. current_date = datetime.now()
  910. # 将年份和月份转换为中文大写数字
  911. year = int(current_date.strftime("%Y")) # 转换为整数
  912. month = int(current_date.strftime("%m")) # 转换为整数
  913. # 使用 cn2an 将数字转换为中文大写
  914. year_chinese = number_to_chinese_year(year) # 年份转换
  915. month_chinese = cn2an.an2cn(month) # 月份转换
  916. current_date_formatted = f"{year_chinese}年{month_chinese}月"
  917. # 组合动态文本
  918. dynamic_text = f"安徽农业大学资源与环境学院\n{current_date_formatted}"
  919. # 添加文字并居中
  920. text_paragraph = doc.add_paragraph()
  921. text_run = text_paragraph.add_run(dynamic_text)
  922. text_run.font.name = "宋体"
  923. text_run.font.size = Pt(18)
  924. text_run.bold = True # 设置字体加粗
  925. text_paragraph.alignment = 1 # 1 表示居中对齐
  926. # 正确插入分页符
  927. doc.add_page_break()
  928. heading = doc.add_heading('总体概述', level=1)
  929. heading.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  930. # 第一段
  931. long_text1 = f"""
  932. {areaName}第三次全国土壤普查县级数据审核报告主要通过收集和整理相关数据,并对其进行内业检测数据的完整性、规范性和合理性进行审核,形成存疑样点清单及存疑样点结果判定,最终编制完成数据审核报告,同时提交( )对相关指标进行整改复测。报告整理了( )个表层样品数据(含平行样、质控样)、( )个水稳性大团聚体样品数据(含平行样)、( )个剖面样品数据(含平行样、质控样),共( )次样品检测结果分析情况。相关结果分别按照物理性指标检测数据、一般化学指标检测数据、常规养分指标检测数据和重金属指标检测数据形成四份报告。本报告为表层样常规养分指标检测数据审核报告。
  933. """
  934. para0 = doc.add_paragraph(long_text1)
  935. run0 = para0.runs[0] # 获取段落中的第一个run对象
  936. run0.font.name = '宋体' # 设置字体为宋体
  937. run0.font.size = Pt(11) # 设置字号为11磅
  938. # 设置段落的行间距为1.5倍
  939. para_format = para0.paragraph_format
  940. para_format.line_spacing = 1.5 # 设置行间距为1.5倍
  941. # 添加一级标题
  942. doc.add_heading('一、数据完整性审核', level=1)
  943. # 第二段
  944. long_text2 = """
  945. 外业信息调查采样环节:采用电子围栏和外业调查采样APP,对采样位置和填报信息进行管理,确保外业调查信息填报完整。
  946. 样品检测数据上报环节:通过土壤普查工作平台对上报数据的完整性进行筛查。( )第三次土壤普查相关指标检测数据由( )提供,数据均已通过省级质控实验室和县级土壤普查办审核;相关土壤指标历史数据则由( )第三次土壤普查办公室提供。根据《第三次全国土壤普查土壤样品制备与检测技术规范(修订版)》要求,统计各土地利用类型的样品数量,并按照耕地园地土壤样品(表层/剖面)、林地草地土壤样品(表层/剖面)以及水稳定性大团聚体样品(见表1)进行分类,编制了指标名称与实际检测样品数量统计表(见表2),其中水溶性盐分总量大于(),增加检测了八大离子(该指标在化学指标检测数据审核报告内)。
  947. """
  948. para = doc.add_paragraph(long_text2)
  949. run1 = para.runs[0]
  950. run1.font.name = '宋体' # 设置字体为宋体
  951. run1.font.size = Pt(11) # 设置字号为11磅
  952. # 设置段落的行间距为1.5倍
  953. para_format = para.paragraph_format
  954. para_format.line_spacing = 1.5 # 设置行间距为1.5倍
  955. #=======================================================================
  956. doc.add_heading('1、土地利用类型与检测指标符合性审核', level=2)
  957. # 插入表格1
  958. paragraph_1 = doc.add_paragraph()
  959. paragraph_1.add_run(f"表1:{areaName}三普样品数量统计表(表层)").bold = True
  960. # 设置居中
  961. paragraph_1.alignment = WD_ALIGN_PARAGRAPH.CENTER
  962. table_1 = doc.add_table(rows=lenNum_1 + 1, cols=3, style='Light Shading Accent 1')
  963. table_1.alignment = WD_TABLE_ALIGNMENT.CENTER
  964. # 遍历表格 插入数据
  965. # 遍历表格的所有单元格,并填充内容
  966. for i, row in enumerate(table_1.rows):
  967. for j, cell in enumerate(row.cells):
  968. # 获取单元格中的段落对象
  969. paragraph = cell.paragraphs[0]
  970. if i == 0:
  971. r = paragraph.add_run(str(table_1_data.columns[j]))
  972. r.font.bold = True
  973. else:
  974. r = paragraph.add_run(str(table_1_data.iloc[i - 1, j]))
  975. r.font.size = Pt(10.5)
  976. r.font.name = 'Times New Roman'
  977. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  978. paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  979. paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  980. paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  981. # 合并单元格 合并第3列的第二行和第三行
  982. if lenNum_1 > 1:
  983. table_1.cell(2, 2).text = ''
  984. table_1.cell(1, 2).merge(table_1.cell(2, 2))
  985. ############test##############
  986. doc.add_heading('2、指标名称与实际检测样品数量完整性审核', level=2)
  987. # 插入表格2
  988. paragraph_2 = doc.add_paragraph()
  989. paragraph_2.add_run(f'表2:{areaName}指标名称与实际检测样品数量统计表').bold = True
  990. table_2 = doc.add_table(rows=len(table_2_data) + 1, cols=3, style='Light Shading Accent 1')
  991. paragraph_2.alignment = WD_ALIGN_PARAGRAPH.CENTER
  992. table_2.alignment = WD_TABLE_ALIGNMENT.CENTER
  993. for i, row in enumerate(table_2.rows):
  994. for j, cell in enumerate(row.cells):
  995. # 获取单元格中的段落对象
  996. paragraph = cell.paragraphs[0]
  997. if i == 0:
  998. r = paragraph.add_run(str(table_2_data.columns[j]))
  999. r.font.bold = True
  1000. else:
  1001. r = paragraph.add_run(str(table_2_data.iloc[i - 1, j]))
  1002. paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  1003. paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  1004. paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  1005. r.font.size = Pt(10.5)
  1006. r.font.name = 'Times New Roman'
  1007. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  1008. doc.add_heading('二、数据规范性审核', level=1)
  1009. long_text3 = """
  1010. 按照《第三次全国土壤普查暂行土壤分类系统 (试行)》、《第三次全国土壤普查工作底图制作与采样点布设技术规范》、《第三次全国土壤普查土壤类型图编制技术规范》《第三次全国土壤普查土壤样品制备与检测技术规范》等规范统一标准和表现形式,土地利用方式按照第三次国土调查土地利用信息统一,种植制度按照农业区划信息进行统一。三普工作平台同时内置指标量纲、数字修约和允差等,控制数据规范性。
  1011. 根据《第三次全国土壤普查土壤样品制备与检测技术规范(修订版)》,对检测指标对应的检测方法与相关标准或规范进行审核,得到检测方法审核、数值修约审核、数据填报项审核结果,未检出项填报以检出限的一半上报并加注*号。根据土壤普查教材中机械组成分类参考表,并进行宁国土壤质地填报审核结果表(见表6)。
  1012. """
  1013. para = doc.add_paragraph(long_text3)
  1014. run1 = para.runs[0]
  1015. run1.font.name = '宋体' # 设置字体为宋体
  1016. run1.font.size = Pt(11) # 设置字号为11磅
  1017. doc.add_heading('1、数据填报规范性审核', level=2)
  1018. # 插入表3
  1019. paragraph_3 = doc.add_paragraph()
  1020. paragraph_3.add_run(f'表3:{areaName}土壤检测数据检测方法填报审核结果表').bold = True
  1021. # table_3 = doc.add_table(rows=2, cols=2)
  1022. paragraph_3.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1023. # table_3.alignment = WD_TABLE_ALIGNMENT.CENTER
  1024. # 写入数据 这里数据写不下 嵌入链接
  1025. doc.add_heading('为避免数据量过多无法显示,请至数据保存文件夹中查看数据表:检测方法审核结果.xlsx', level=4)
  1026. doc.add_heading('2、数值修约规范性审核', level=2)
  1027. # 插入表4
  1028. paragraph_4 = doc.add_paragraph()
  1029. paragraph_4.add_run(f'表4:{areaName}土壤检测数据数值修约结果表').bold = True
  1030. # table_4 = doc.add_table(rows=2, cols=2)
  1031. paragraph_4.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1032. # table_4.alignment = WD_TABLE_ALIGNMENT.CENTER
  1033. doc.add_heading('为避免数据量过多无法显示,请至数据保存文件夹中查看数据表:数值修约审核.xlsx', level=4)
  1034. # 填入数据 这里数据也放不下 嵌入链接
  1035. doc.add_heading('3、数据未检出的填报规范性审核', level=2)
  1036. # 插入表5
  1037. paragraph_5 = doc.add_paragraph()
  1038. paragraph_5.add_run(f'表5:{areaName}土壤检测数据未检出项填报审核结果表').bold = True
  1039. # table_5 = doc.add_table(rows=2, cols=2)
  1040. paragraph_5.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1041. # table_5.alignment = WD_TABLE_ALIGNMENT.CENTER
  1042. # 写入数据 这里数据也放不下 嵌入链接
  1043. doc.add_heading('为避免数据量过多无法显示,请至数据保存文件夹中查看数据表:数据填报项审核结果.xlsx', level=4)
  1044. # doc.add_heading('4、土壤质地填报规范性审核', level=2)
  1045. # 插入表6
  1046. # paragraph_6 = doc.add_paragraph()
  1047. # paragraph_6.add_run(f'表6:{areaName}土壤质地填报审核结果表').bold = True
  1048. # table_6 = doc.add_table(rows=len(table_6_data) + 1, cols=4, style='Light Shading Accent 1')
  1049. # paragraph_6.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1050. # table_6.alignment = WD_TABLE_ALIGNMENT.CENTER
  1051. # # 提取结果表中数据
  1052. # # 写入数据 土壤质地类型不一致的数据提取出来
  1053. # for i, row in enumerate(table_6.rows):
  1054. # for j, cell in enumerate(row.cells):
  1055. # # 获取单元格中的段落对象
  1056. # paragraph = cell.paragraphs[0]
  1057. # if i == 0:
  1058. # r = paragraph.add_run(str(table_6_data.columns[j]))
  1059. # r.font.bold = True
  1060. # else:
  1061. # r = paragraph.add_run(str(table_6_data.iloc[i - 1, j]))
  1062. # paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  1063. # paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  1064. # paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  1065. # r.font.size = Pt(10.5)
  1066. # r.font.name = 'Times New Roman'
  1067. # r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  1068. doc.add_heading('三、数据合理性审核', level=1)
  1069. long_text4 = """
  1070. 明确数据审核原则,结合外业调查采样,获取的成土环境、土壤利用现状等信息对结果进行综合评价。通过阈值分析、关联分析、逻辑分析等方法对数据准确性进行判断。
  1071. 阈值法(国家和省级数据阈值):结合区域历史数据建立阈值,平台利用阈值法(国家和省级数据值)自动对检测数据进行初步审核,并对超出阈值范围数据做出警示标识,专家或专业技术人员结合区域实际、专家经验判定异常值并对异常数据进行驳回。超出阈值颜色标注。
  1072. 红色: 超出国家阈值,维持试点期间的标红。
  1073. 黄色: 省级阈值在国家阈值范围内的,数据超出省级阈值标黄。
  1074. 紫色: 省级阈值超出国家阈值的,数据超出省级阈值标成紫色(注,此种情况超国家阈值的红色服从紫色,仅标紫色)
  1075. 极值法: 常用的统计量是均值、标准差、最大值、最小值、分位数等,用来判断是否超出了合理的极值范围。根据相关指标历年数据与指标最大值、最小值、平均数、中位数和极差进行审查,结合相关外业情况。
  1076. 关联分析方法: 存在量化关系的指标,通过设定组合筛选异常值,如碳氮比等关联分析。
  1077. 指标综合分析:根据指标相互之间的关系,如有效磷在全磷中的占比、全钾与速效钾缓效钾之和的关系等。有机质、全磷、有效磷、全钾等数据异常; 全氮和有机质之间关系不合理; 速效钾含量远大于缓效钾,盐基总量远大于阳离子交换量; 部分样品阳离子交换量和交换性盐基总量测定结果偏低; 水溶盐离子总量与全盐量的相对偏差已远超过方法规定的允差范围; 容重检测偏差比较大;水稳性大团聚体土壤干燥结块,影响测定结果、重金属按照风险筛选值和风险管控值等问题。
  1078. 数据质量溯源:异常数据溯源,可能是内业测试化验环节问题,也有可能是外业调查采样问题,要结合数据检测和异常复检情况具体判断。
  1079. """
  1080. para = doc.add_paragraph(long_text4)
  1081. run1 = para.runs[0]
  1082. run1.font.name = '宋体' # 设置字体为宋体
  1083. run1.font.size = Pt(11) # 设置字号为11磅
  1084. doc.add_heading('1、阈值法审核', level=2)
  1085. # 插入表格
  1086. paragraph_7 = doc.add_paragraph()
  1087. paragraph_7.add_run(f'表6:{areaName}土壤检测数据超阈值样品统计表').bold = True
  1088. # table_7 = doc.add_table(rows=2, cols=2)
  1089. # paragraph_7.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1090. # table_7.alignment = WD_TABLE_ALIGNMENT.CENTER
  1091. # 写入数据 点击查看数据 这里也不一定写的下 最好是嵌入链接
  1092. doc.add_heading('为避免数据量过多无法显示,请至数据保存文件夹中查看数据表:数据审核过程存疑数据一览表.xlsx', level=4)
  1093. # todo 合并所有数据 审核结果不为空的数据 写入表格保存到指定文件夹
  1094. doc.add_heading('2、极值法审核', level=2)
  1095. doc.add_heading('(1)pH', level=3)
  1096. # 插入ph分布图
  1097. if os.path.isfile(f'{mkdir_path}/PH值分布图.png'):
  1098. doc.add_picture(f'{mkdir_path}/PH值分布图.png', width=Inches(6.0))
  1099. paragraph_t_1 = doc.add_paragraph()
  1100. paragraph_t_1.add_run(f'图1:pH值分布情况').bold = True
  1101. paragraph_t_1.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1102. # 插入频度统计表
  1103. paragraph_8 = doc.add_paragraph()
  1104. paragraph_8.add_run('表7:pH数据统计表').bold = True
  1105. table_8 = doc.add_table(rows=6, cols=2, style='Light Shading Accent 1')
  1106. t_8 = table_8_data['频度分析']
  1107. t_8 = t_8.reset_index()
  1108. t_8.columns = ['指标', '数据']
  1109. paragraph_8.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1110. table_8.alignment = WD_TABLE_ALIGNMENT.CENTER
  1111. for i, row in enumerate(table_8.rows):
  1112. for j, cell in enumerate(row.cells):
  1113. # 获取单元格中的段落对象
  1114. paragraph = cell.paragraphs[0]
  1115. if i == 0:
  1116. r = paragraph.add_run(str(t_8.columns[j]))
  1117. r.font.bold = True
  1118. else:
  1119. r = paragraph.add_run(str(t_8.iloc[i - 1, j]))
  1120. r.font.size = Pt(10.5)
  1121. r.font.name = 'Times New Roman'
  1122. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  1123. paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  1124. paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  1125. paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  1126. # 插入异常数据提取表格 todo 这里数据多的话也可能写不下 最好是嵌入一下
  1127. if not table_8_data['异常数据'].empty:
  1128. paragraph_9 = doc.add_paragraph()
  1129. paragraph_9.add_run('表8:pH异常数据统计表').bold = True
  1130. table_9 = doc.add_table(rows=len(table_8_data['异常数据']) + 1, cols=6, style='Light Shading Accent 1')
  1131. t_9 = table_8_data['异常数据']
  1132. paragraph_9.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1133. table_9.alignment = WD_TABLE_ALIGNMENT.CENTER
  1134. for i, row in enumerate(table_9.rows):
  1135. for j, cell in enumerate(row.cells):
  1136. # 获取单元格中的段落对象
  1137. paragraph = cell.paragraphs[0]
  1138. if i == 0:
  1139. r = paragraph.add_run(str(t_9.columns[j]))
  1140. r.font.bold = True
  1141. else:
  1142. r = paragraph.add_run(str(t_9.iloc[i - 1, j]))
  1143. r.font.size = Pt(10.5)
  1144. r.font.name = 'Times New Roman'
  1145. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  1146. paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  1147. paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  1148. paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  1149. doc.add_heading('3、关联分析法审核', level=2)
  1150. if os.path.isfile(f'{mkdir_path}/有机质与全氮相关性分析图.png'):
  1151. doc.add_picture(f'{mkdir_path}/有机质与全氮相关性分析图.png', width=Inches(6.0))
  1152. paragraph_t_2 = doc.add_paragraph()
  1153. paragraph_t_2.add_run(f'图2:有机质与全氮相关关系').bold = True
  1154. paragraph_t_2.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1155. # 插入碳氮比异常数据
  1156. if not table_10_data.empty:
  1157. paragraph_10 = doc.add_paragraph()
  1158. paragraph_10.add_run('表9:碳氮比异常数据统计表').bold = True
  1159. table_10 = doc.add_table(rows=len(table_10_data) + 1, cols=8, style='Light Shading Accent 1')
  1160. paragraph_10.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1161. table_10.alignment = WD_TABLE_ALIGNMENT.CENTER
  1162. for i, row in enumerate(table_10.rows):
  1163. for j, cell in enumerate(row.cells):
  1164. # 获取单元格中的段落对象
  1165. paragraph = cell.paragraphs[0]
  1166. if i == 0:
  1167. r = paragraph.add_run(str(table_10_data.columns[j]))
  1168. r.font.bold = True
  1169. else:
  1170. r = paragraph.add_run(str(table_10_data.iloc[i - 1, j]))
  1171. r.font.size = Pt(10.5)
  1172. r.font.name = 'Times New Roman'
  1173. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  1174. paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  1175. paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  1176. paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  1177. doc.add_heading('4、指标综合分析', level=2)
  1178. # 插入图片
  1179. if os.path.isfile(f'{mkdir_path}/全磷分布图.png'):
  1180. doc.add_picture(f'{mkdir_path}/全磷分布图.png', width=Inches(6.0))
  1181. paragraph_t_3 = doc.add_paragraph()
  1182. paragraph_t_3.add_run(f'图3:全磷分布图').bold = True
  1183. paragraph_t_3.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1184. if os.path.isfile(f'{mkdir_path}/有效磷分布图.png'):
  1185. doc.add_picture(f'{mkdir_path}/有效磷分布图.png', width=Inches(6.0))
  1186. paragraph_t_4 = doc.add_paragraph()
  1187. paragraph_t_4.add_run(f'图4:有效磷分布图').bold = True
  1188. paragraph_t_4.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1189. # 插入图片
  1190. if os.path.isfile(f'{mkdir_path}/有效磷占全磷比分布图.png'):
  1191. doc.add_picture(f'{mkdir_path}/有效磷占全磷比分布图.png', width=Inches(6.0))
  1192. paragraph_t_5 = doc.add_paragraph()
  1193. paragraph_t_5.add_run(f'图5:有效磷含量占全磷含量比例').bold = True
  1194. paragraph_t_5.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1195. # 插入表格
  1196. if not table_11_data.empty:
  1197. paragraph_11 = doc.add_paragraph()
  1198. paragraph_11.add_run('表10:全磷与有效磷异常样品统计表').bold = True
  1199. table_11 = doc.add_table(rows=len(table_11_data) + 1, cols=7, style='Light Shading Accent 1')
  1200. paragraph_11.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1201. table_11.alignment = WD_TABLE_ALIGNMENT.CENTER
  1202. for i, row in enumerate(table_11.rows):
  1203. for j, cell in enumerate(row.cells):
  1204. # 获取单元格中的段落对象
  1205. paragraph = cell.paragraphs[0]
  1206. if i == 0:
  1207. r = paragraph.add_run(str(table_11_data.columns[j]))
  1208. r.font.bold = True
  1209. else:
  1210. r = paragraph.add_run(str(table_11_data.iloc[i - 1, j]))
  1211. r.font.size = Pt(10.5)
  1212. r.font.name = 'Times New Roman'
  1213. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  1214. paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  1215. paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  1216. paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  1217. else:
  1218. paragraph_11 = doc.add_paragraph()
  1219. paragraph_11.add_run('表10:全磷与有效磷异常样品统计表').bold = True
  1220. paragraph_11_info = doc.add_paragraph()
  1221. paragraph_11_info.add_run('无异常数据')
  1222. paragraph_11.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1223. paragraph_11_info.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1224. # 全钾、速效钾、缓效钾
  1225. if os.path.isfile(f'{mkdir_path}/全钾与速效钾缓效钾之和关系统计图.png'):
  1226. doc.add_picture(f'{mkdir_path}/全钾与速效钾缓效钾之和关系统计图.png', width=Inches(6.0))
  1227. paragraph_t_6 = doc.add_paragraph()
  1228. paragraph_t_6.add_run(f'图6:全钾与速效钾缓效钾之和关系统计图').bold = True
  1229. paragraph_t_6.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1230. if os.path.isfile(f'{mkdir_path}/速效钾与缓效钾关系统计图.png'):
  1231. doc.add_picture(f'{mkdir_path}/速效钾与缓效钾关系统计图.png', width=Inches(6.0))
  1232. paragraph_t_7 = doc.add_paragraph()
  1233. paragraph_t_7.add_run(f'图7:速效钾与缓效钾关系统计图').bold = True
  1234. paragraph_t_7.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1235. doc.add_heading('四、审核存疑数据', level=1)
  1236. paragraph_12 = doc.add_paragraph()
  1237. paragraph_12.add_run(f'表11:数据审核过程存疑数据一览表').bold = True
  1238. paragraph_12.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1239. doc.add_heading('为避免数据量过多无法显示,请至数据保存文件夹中查看数据表:数据审核过程存疑数据一览表.xlsx', level=4)
  1240. doc.add_heading('五、附表', level=1)
  1241. doc.add_heading('附表1:某区三普样品数量统计表(表层)', level=2)
  1242. # 插入附表1
  1243. table_1_f = doc.add_table(rows=lenNum_1 + 1, cols=3, style='Light Shading Accent 1')
  1244. table_1_f.alignment = WD_TABLE_ALIGNMENT.CENTER
  1245. # 遍历表格 插入数据
  1246. # 遍历表格的所有单元格,并填充内容
  1247. for i, row in enumerate(table_1_f.rows):
  1248. for j, cell in enumerate(row.cells):
  1249. # 获取单元格中的段落对象
  1250. paragraph = cell.paragraphs[0]
  1251. if i == 0:
  1252. r = paragraph.add_run(str(table_1_data.columns[j]))
  1253. r.font.bold = True
  1254. else:
  1255. r = paragraph.add_run(str(table_1_data.iloc[i - 1, j]))
  1256. r.font.size = Pt(10.5)
  1257. r.font.name = 'Times New Roman'
  1258. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  1259. paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  1260. paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  1261. paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  1262. # 合并单元格 合并第3列的第二行和第三行
  1263. if lenNum_1 > 1:
  1264. table_1_f.cell(2, 2).text = ''
  1265. table_1_f.cell(1, 2).merge(table_1_f.cell(2, 2))
  1266. doc.add_heading('附表2:各指标频度分析表', level=2)
  1267. # 插入表格 写入数据
  1268. table_f_2_data = table_f_2_data.replace(np.nan, '')
  1269. makeInfoTable(table_f_2_data, doc)
  1270. # table_f_2 = doc.add_table(rows=len(table_f_2_data) + 1, cols=6, style='Light Shading Accent 1')
  1271. # for i, row in enumerate(table_f_2.rows):
  1272. # for j, cell in enumerate(row.cells):
  1273. # # 获取单元格中的段落对象
  1274. # paragraph = cell.paragraphs[0]
  1275. # if i == 0:
  1276. # r = paragraph.add_run(str(table_f_2_data.columns[j]))
  1277. # r.font.bold = True
  1278. # else:
  1279. # r = paragraph.add_run(str(table_f_2_data.iloc[i - 1, j]))
  1280. # r.font.size = Pt(10.5)
  1281. # r.font.name = 'Times New Roman'
  1282. # r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  1283. # paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  1284. # paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  1285. # paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  1286. # doc.add_heading('为避免数据量过多无法显示,请至数据保存文件夹中查看数据表:频度分析表.xlsx', level=4)
  1287. doc.add_heading('附表3:各指标频度分析图', level=2)
  1288. # 插入频度信息的图形
  1289. if os.path.isfile(f'{mkdir_path}/pH分析图.png'):
  1290. doc.add_picture(f'{mkdir_path}/pH分析图.png', width=Inches(6.0))
  1291. if os.path.isfile(f'{mkdir_path}/缓效钾分析图.png'):
  1292. doc.add_picture(f'{mkdir_path}/缓效钾分析图.png', width=Inches(6.0))
  1293. if os.path.isfile(f'{mkdir_path}/全氮分析图.png'):
  1294. doc.add_picture(f'{mkdir_path}/全氮分析图.png', width=Inches(6.0))
  1295. if os.path.isfile(f'{mkdir_path}/全钾分析图.png'):
  1296. doc.add_picture(f'{mkdir_path}/全钾分析图.png', width=Inches(6.0))
  1297. if os.path.isfile(f'{mkdir_path}/全磷分析图.png'):
  1298. doc.add_picture(f'{mkdir_path}/全磷分析图.png', width=Inches(6.0))
  1299. if os.path.isfile(f'{mkdir_path}/速效钾分析图.png'):
  1300. doc.add_picture(f'{mkdir_path}/速效钾分析图.png', width=Inches(6.0))
  1301. if os.path.isfile(f'{mkdir_path}/有机质分析图.png'):
  1302. doc.add_picture(f'{mkdir_path}/有机质分析图.png', width=Inches(6.0))
  1303. if os.path.isfile(f'{mkdir_path}/有效硅分析图.png'):
  1304. doc.add_picture(f'{mkdir_path}/有效硅分析图.png', width=Inches(6.0))
  1305. if os.path.isfile(f'{mkdir_path}/有效磷分析图.png'):
  1306. doc.add_picture(f'{mkdir_path}/有效磷分析图.png', width=Inches(6.0))
  1307. if os.path.isfile(f'{mkdir_path}/有效硫分析图.png'):
  1308. doc.add_picture(f'{mkdir_path}/有效硫分析图.png', width=Inches(6.0))
  1309. if os.path.isfile(f'{mkdir_path}/有效锰分析图.png'):
  1310. doc.add_picture(f'{mkdir_path}/有效锰分析图.png', width=Inches(6.0))
  1311. if os.path.isfile(f'{mkdir_path}/有效钼分析图.png'):
  1312. doc.add_picture(f'{mkdir_path}/有效钼分析图.png', width=Inches(6.0))
  1313. if os.path.isfile(f'{mkdir_path}/有效硼分析图.png'):
  1314. doc.add_picture(f'{mkdir_path}/有效硼分析图.png', width=Inches(6.0))
  1315. if os.path.isfile(f'{mkdir_path}/有效铁分析图.png'):
  1316. doc.add_picture(f'{mkdir_path}/有效铁分析图.png', width=Inches(6.0))
  1317. if os.path.isfile(f'{mkdir_path}/有效铜分析图.png'):
  1318. doc.add_picture(f'{mkdir_path}/有效铜分析图.png', width=Inches(6.0))
  1319. if os.path.isfile(f'{mkdir_path}/有效锌分析图.png'):
  1320. doc.add_picture(f'{mkdir_path}/有效锌分析图.png', width=Inches(6.0))
  1321. doc.add_heading('附表4:数值修约标准', level=2)
  1322. # 读取数据 插入表格 写入数据
  1323. numData = pd.read_excel('./img/数值修约要求.xlsx', sheet_name='Sheet1')
  1324. table_2_f = doc.add_table(rows=len(numData) + 1, cols=2, style='Light Shading Accent 1')
  1325. table_2_f.alignment = WD_TABLE_ALIGNMENT.CENTER
  1326. for i, row in enumerate(table_2_f.rows):
  1327. for j, cell in enumerate(row.cells):
  1328. # 获取单元格中的段落对象
  1329. paragraph = cell.paragraphs[0]
  1330. if i == 0:
  1331. r = paragraph.add_run(str(numData.columns[j]))
  1332. r.font.bold = True
  1333. else:
  1334. r = paragraph.add_run(str(numData.iloc[i - 1, j]))
  1335. r.font.size = Pt(10.5)
  1336. r.font.name = 'Times New Roman'
  1337. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  1338. paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  1339. paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  1340. paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  1341. # 处理样式 遍历所有的段落 修改字体
  1342. # 遍历并打印每个段落的文本
  1343. paragraphs = doc.paragraphs
  1344. for paragraph in paragraphs:
  1345. for run in paragraph.runs:
  1346. run.font.color.rgb = RGBColor(0, 0, 0)
  1347. run.font.name = 'Times New Roman'
  1348. run.font.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  1349. # 保存Word文档
  1350. doc.save(f'{mkdir_path}/{areaName}-{type}审核报告.docx')
  1351. # 生成一般化学性指标审核报告
  1352. def getChemicalIndicators(originData, data,type, changeFileUrl, saveFileUrl, check_1_data,
  1353. check_3_data,
  1354. check_5_data,
  1355. check_8_data, # 样品编号替换为编号
  1356. check_10_data,
  1357. check_12_data,
  1358. check_14_data):
  1359. # 生成报告
  1360. name = os.path.basename(changeFileUrl)
  1361. n = name.split('.')
  1362. areaName = n[0].replace('数据', '')
  1363. # 生成一个新的文件夹用于存放审核报告相关的数据
  1364. nowTime = time.strftime("%Y-%m-%d %H时%M分%S秒", time.localtime())
  1365. dir_name = f'{areaName}-{type}数据审核报告'
  1366. mkdir_path = saveFileUrl + '/' + dir_name + nowTime
  1367. if not os.path.exists(mkdir_path):
  1368. os.mkdir(mkdir_path)
  1369. # 根据选择的路径读取数据
  1370. cheemicalData = data[indexClassificationList[type]]
  1371. cheemicalDataNum = originData[indexClassificationList[type]]
  1372. report.getFrequencyImage(cheemicalData, mkdir_path)
  1373. cheemicalData['序号'] = data['序号']
  1374. cheemicalData['原样品编号'] = data['原样品编号']
  1375. cheemicalData['样品编号'] = data['样品编号']
  1376. cheemicalData['地理位置'] = data['地理位置']
  1377. cheemicalData['母质'] = data['母质']
  1378. cheemicalData['土壤类型'] = data['土壤类型']
  1379. cheemicalData['土地利用类型'] = data['土地利用类型']
  1380. # cheemicalData['土壤质地'] = data['土壤质地']
  1381. cheemicalData['原样品编号'] = cheemicalData['原样品编号'].astype(str)
  1382. # checkData = pd.read_excel(changeFileUrl, sheet_name='检测方法')
  1383. cheemicalDataNum['序号'] = originData['序号']
  1384. cheemicalDataNum['原样品编号'] = originData['原样品编号']
  1385. cheemicalDataNum['样品编号'] = originData['样品编号']
  1386. cheemicalDataNum['地理位置'] = originData['地理位置']
  1387. cheemicalDataNum['母质'] = originData['母质']
  1388. cheemicalDataNum['土壤类型'] = originData['土壤类型']
  1389. cheemicalDataNum['土地利用类型'] = originData['土地利用类型']
  1390. # cheemicalData['土壤质地'] = data['土壤质地']
  1391. cheemicalDataNum['原样品编号'] = cheemicalDataNum['原样品编号'].astype(str)
  1392. # 上面这个地址,可以纯递给函数中,用于保存表格和图片
  1393. # 调用函数 开始生成报告相关内容
  1394. # 表1相关数据
  1395. typeData = report.getSimpleNum(cheemicalData)
  1396. lenNum_1 = len(typeData['sData'])
  1397. lenNum_1_f = len(typeData['allData'])
  1398. table_1_data = pd.DataFrame({
  1399. '类型': typeData['sData'].index,
  1400. '数量': typeData['sData'],
  1401. '合计': [typeData['sData'].sum() for _ in range(lenNum_1)]
  1402. })
  1403. # 表2数据
  1404. table_2_data = report.getDataComplete(cheemicalData)
  1405. table_2_data = table_2_data.reset_index()
  1406. table_2_data.columns = ['指标名称', '实测数量', '应测数量']
  1407. # 表3数据
  1408. # table_3_data = report.checkMethod(checkData, mkdir_path)
  1409. # 数据修约 表4
  1410. report.getNum(cheemicalData, mkdir_path)
  1411. # 数据填报项审核 表5
  1412. report.dataReportResult(cheemicalData, mkdir_path)
  1413. # 表6数据 土壤质地类型不一致
  1414. middData = data[['原样品编号', '样品编号']].astype(str)
  1415. middData['编号'] = middData['原样品编号']
  1416. del middData['原样品编号']
  1417. check_1_data = pd.merge(check_1_data, middData, how='left', on='编号')
  1418. check_1_data = check_1_data.replace(np.nan, '')
  1419. # typeNotSame = check_1_data[check_1_data['土壤质地'] != check_1_data['土壤类型(判断)']]
  1420. # table_6_data = typeNotSame[['编号', '样品编号', '土壤质地', '土壤类型(判断)']]
  1421. allNeedData = pd.DataFrame({})
  1422. allNeedData['原样品编号'] = check_1_data['编号']
  1423. getSimpleDataNumber = pd.merge(allNeedData, data[['原样品编号', '样品编号']], how='left', on="原样品编号")
  1424. allNeedData['样品编号'] = getSimpleDataNumber['样品编号']
  1425. allNeedData['土地利用类型'] = check_1_data['土地利用类型']
  1426. allNeedData['审核结果'] = check_5_data['审核结果'] + check_8_data['审核结果']
  1427. allNeedData['外业'] = ['' for _ in range(len(check_1_data))]
  1428. table_7_data = allNeedData[allNeedData['审核结果'] != '']
  1429. del table_7_data['审核结果']
  1430. # 写进表格
  1431. with pd.ExcelWriter(f'{mkdir_path}/超阈值样品统计表.xlsx', engine='openpyxl') as writer:
  1432. table_7_data.to_excel(writer, index=False, sheet_name='超阈值数据')
  1433. # 表8数据
  1434. table_8_data = report.getPHData(cheemicalData, mkdir_path)
  1435. report.cationExchangeCapacity(cheemicalData, mkdir_path)
  1436. report.changeCation(cheemicalData, mkdir_path)
  1437. report.manyTypes(cheemicalData, mkdir_path)
  1438. # 有效态异常数据
  1439. errObj = report.orderData(data)
  1440. # 表13 所有存疑数据
  1441. with pd.ExcelWriter(f'{mkdir_path}/数据审核过程存疑数据一览表.xlsx', engine='openpyxl') as writer:
  1442. allNeedData[allNeedData['审核结果'] != ''].to_excel(writer, index=False, sheet_name='存疑数据')
  1443. # 附表: 频度分析图
  1444. # report.getFrequencyImage(cheemicalData, mkdir_path)
  1445. table_f_2_data = report.getFrequencyInformation(data, mkdir_path)
  1446. # 新建一个文档
  1447. doc = Document()
  1448. # 添加标题
  1449. doc.add_heading(f"{areaName}第三次全国土壤普查一般化学性数据审核报告", level=0)
  1450. # 在文档中添加封面段落
  1451. fm = doc.add_paragraph()
  1452. fm = doc.add_paragraph()
  1453. fm = doc.add_paragraph()
  1454. fm = doc.add_paragraph()
  1455. fm = doc.add_paragraph()
  1456. # 插入图片,设置宽度为6英寸(可根据需求调整)
  1457. run = fm.add_run()
  1458. run.add_picture('img/第三次全国土壤普查img.png', width=Inches(2.26))
  1459. fm.alignment = WD_TABLE_ALIGNMENT.CENTER
  1460. # 在文档中添加封面段落
  1461. fm = doc.add_paragraph()
  1462. fm = doc.add_paragraph()
  1463. fm = doc.add_paragraph()
  1464. fm = doc.add_paragraph()
  1465. fm = doc.add_paragraph()
  1466. fm = doc.add_paragraph()
  1467. # 获取当前日期
  1468. current_date = datetime.now()
  1469. # 将年份和月份转换为中文大写数字
  1470. year = int(current_date.strftime("%Y")) # 转换为整数
  1471. month = int(current_date.strftime("%m")) # 转换为整数
  1472. # 使用 cn2an 将数字转换为中文大写
  1473. year_chinese = number_to_chinese_year(year) # 年份转换
  1474. month_chinese = cn2an.an2cn(month) # 月份转换
  1475. current_date_formatted = f"{year_chinese}年{month_chinese}月"
  1476. # 组合动态文本
  1477. dynamic_text = f"安徽农业大学资源与环境学院\n{current_date_formatted}"
  1478. # 添加文字并居中
  1479. text_paragraph = doc.add_paragraph()
  1480. text_run = text_paragraph.add_run(dynamic_text)
  1481. text_run.font.name = "宋体"
  1482. text_run.font.size = Pt(18)
  1483. text_run.bold = True # 设置字体加粗
  1484. text_paragraph.alignment = 1 # 1 表示居中对齐
  1485. # 正确插入分页符
  1486. doc.add_page_break()
  1487. heading = doc.add_heading('总体概述', level=1)
  1488. heading.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  1489. # 第一段
  1490. long_text1 = f"""
  1491. {areaName}第三次全国土壤普查县级数据审核报告主要通过收集和整理相关数据,并对其进行内业检测数据的完整性、规范性和合理性进行审核,形成存疑样点清单及存疑样点结果判定,最终编制完成数据审核报告,同时提交( )对相关指标进行整改复测。报告整理了( )个表层样品数据(含平行样、质控样)、( )个水稳性大团聚体样品数据(含平行样)、( )个剖面样品数据(含平行样、质控样),共( )次样品检测结果分析情况。相关结果分别按照物理性指标检测数据、一般化学指标检测数据、常规养分指标检测数据和重金属指标检测数据形成四份报告。本报告为表层样常规养分指标检测数据审核报告。
  1492. """
  1493. para0 = doc.add_paragraph(long_text1)
  1494. run0 = para0.runs[0] # 获取段落中的第一个run对象
  1495. run0.font.name = '宋体' # 设置字体为宋体
  1496. run0.font.size = Pt(11) # 设置字号为11磅
  1497. # 设置段落的行间距为1.5倍
  1498. para_format = para0.paragraph_format
  1499. para_format.line_spacing = 1.5 # 设置行间距为1.5倍
  1500. # 添加一级标题
  1501. doc.add_heading('一、数据完整性审核', level=1)
  1502. # 第二段
  1503. long_text2 = """
  1504. 外业信息调查采样环节:采用电子围栏和外业调查采样APP,对采样位置和填报信息进行管理,确保外业调查信息填报完整。
  1505. 样品检测数据上报环节:通过土壤普查工作平台对上报数据的完整性进行筛查。( )第三次土壤普查相关指标检测数据由( )提供,数据均已通过省级质控实验室和县级土壤普查办审核;相关土壤指标历史数据则由( )第三次土壤普查办公室提供。根据《第三次全国土壤普查土壤样品制备与检测技术规范(修订版)》要求,统计各土地利用类型的样品数量,并按照耕地园地土壤样品(表层/剖面)、林地草地土壤样品(表层/剖面)以及水稳定性大团聚体样品(见表1)进行分类,编制了指标名称与实际检测样品数量统计表(见表2),其中水溶性盐分总量大于(),增加检测了八大离子(该指标在化学指标检测数据审核报告内)。
  1506. """
  1507. para = doc.add_paragraph(long_text2)
  1508. run1 = para.runs[0]
  1509. run1.font.name = '宋体' # 设置字体为宋体
  1510. run1.font.size = Pt(11) # 设置字号为11磅
  1511. # 设置段落的行间距为1.5倍
  1512. para_format = para.paragraph_format
  1513. para_format.line_spacing = 1.5 # 设置行间距为1.5倍
  1514. doc.add_heading('1、土地利用类型与检测指标符合性审核', level=2)
  1515. # 插入表格1
  1516. paragraph_1 = doc.add_paragraph()
  1517. paragraph_1.add_run(f"表1:{areaName}三普样品数量统计表(表层)").bold = True
  1518. # 设置居中
  1519. paragraph_1.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1520. table_1 = doc.add_table(rows=lenNum_1 + 1, cols=3, style='Light Shading Accent 1')
  1521. table_1.alignment = WD_TABLE_ALIGNMENT.CENTER
  1522. # 遍历表格 插入数据
  1523. # 遍历表格的所有单元格,并填充内容
  1524. for i, row in enumerate(table_1.rows):
  1525. for j, cell in enumerate(row.cells):
  1526. # 获取单元格中的段落对象
  1527. paragraph = cell.paragraphs[0]
  1528. if i == 0:
  1529. r = paragraph.add_run(str(table_1_data.columns[j]))
  1530. r.font.bold = True
  1531. else:
  1532. r = paragraph.add_run(str(table_1_data.iloc[i - 1, j]))
  1533. r.font.size = Pt(10.5)
  1534. r.font.name = 'Times New Roman'
  1535. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  1536. paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  1537. paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  1538. paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  1539. # 合并单元格 合并第3列的第二行和第三行
  1540. if lenNum_1 > 1:
  1541. table_1.cell(2, 2).text = ''
  1542. table_1.cell(1, 2).merge(table_1.cell(2, 2))
  1543. ############test##############
  1544. doc.add_heading('2、指标名称与实际检测样品数量完整性审核', level=2)
  1545. # 插入表格2
  1546. paragraph_2 = doc.add_paragraph()
  1547. paragraph_2.add_run(f'表2:{areaName}指标名称与实际检测样品数量统计表').bold = True
  1548. table_2 = doc.add_table(rows=len(table_2_data) + 1, cols=3, style='Light Shading Accent 1')
  1549. paragraph_2.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1550. table_2.alignment = WD_TABLE_ALIGNMENT.CENTER
  1551. for i, row in enumerate(table_2.rows):
  1552. for j, cell in enumerate(row.cells):
  1553. # 获取单元格中的段落对象
  1554. paragraph = cell.paragraphs[0]
  1555. if i == 0:
  1556. r = paragraph.add_run(str(table_2_data.columns[j]))
  1557. r.font.bold = True
  1558. else:
  1559. r = paragraph.add_run(str(table_2_data.iloc[i - 1, j]))
  1560. paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  1561. paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  1562. paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  1563. r.font.size = Pt(10.5)
  1564. r.font.name = 'Times New Roman'
  1565. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  1566. doc.add_heading('二、数据规范性审核', level=1)
  1567. long_text3 = """
  1568. 按照《第三次全国土壤普查暂行土壤分类系统 (试行)》、《第三次全国土壤普查工作底图制作与采样点布设技术规范》、《第三次全国土壤普查土壤类型图编制技术规范》《第三次全国土壤普查土壤样品制备与检测技术规范》等规范统一标准和表现形式,土地利用方式按照第三次国土调查土地利用信息统一,种植制度按照农业区划信息进行统一。三普工作平台同时内置指标量纲、数字修约和允差等,控制数据规范性。
  1569. 根据《第三次全国土壤普查土壤样品制备与检测技术规范(修订版)》,对检测指标对应的检测方法与相关标准或规范进行审核,得到检测方法审核、数值修约审核、数据填报项审核结果,未检出项填报以检出限的一半上报并加注*号。根据土壤普查教材中机械组成分类参考表,并进行宁国土壤质地填报审核结果表(见表6)。
  1570. """
  1571. para = doc.add_paragraph(long_text3)
  1572. run1 = para.runs[0]
  1573. run1.font.name = '宋体' # 设置字体为宋体
  1574. run1.font.size = Pt(11) # 设置字号为11磅
  1575. doc.add_heading('1、数据填报规范性审核', level=2)
  1576. # 插入表3
  1577. paragraph_3 = doc.add_paragraph()
  1578. paragraph_3.add_run(f'表3:{areaName}土壤检测数据检测方法填报审核结果表').bold = True
  1579. # table_3 = doc.add_table(rows=2, cols=2)
  1580. paragraph_3.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1581. # table_3.alignment = WD_TABLE_ALIGNMENT.CENTER
  1582. # 写入数据 这里数据写不下 嵌入链接
  1583. doc.add_heading('为避免数据量过多无法显示,请至数据保存文件夹中查看数据表:检测方法审核结果.xlsx', level=4)
  1584. doc.add_heading('2、数值修约规范性审核', level=2)
  1585. # 插入表4
  1586. paragraph_4 = doc.add_paragraph()
  1587. paragraph_4.add_run(f'表4:{areaName}土壤检测数据数值修约结果表').bold = True
  1588. # table_4 = doc.add_table(rows=2, cols=2)
  1589. paragraph_4.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1590. # table_4.alignment = WD_TABLE_ALIGNMENT.CENTER
  1591. doc.add_heading('为避免数据量过多无法显示,请至数据保存文件夹中查看数据表:数值修约审核.xlsx', level=4)
  1592. # 填入数据 这里数据也放不下 嵌入链接
  1593. doc.add_heading('3、数据未检出的填报规范性审核', level=2)
  1594. # 插入表5
  1595. paragraph_5 = doc.add_paragraph()
  1596. paragraph_5.add_run(f'表5:{areaName}土壤检测数据未检出项填报审核结果表').bold = True
  1597. # table_5 = doc.add_table(rows=2, cols=2)
  1598. paragraph_5.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1599. # table_5.alignment = WD_TABLE_ALIGNMENT.CENTER
  1600. # 写入数据 这里数据也放不下 嵌入链接
  1601. doc.add_heading('为避免数据量过多无法显示,请至数据保存文件夹中查看数据表:数据填报项审核结果.xlsx', level=4)
  1602. # doc.add_heading('4、土壤质地填报规范性审核', level=2)
  1603. # 插入表6
  1604. # paragraph_6 = doc.add_paragraph()
  1605. # paragraph_6.add_run(f'表6:{areaName}土壤质地填报审核结果表').bold = True
  1606. # table_6 = doc.add_table(rows=len(table_6_data) + 1, cols=4, style='Light Shading Accent 1')
  1607. # paragraph_6.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1608. # table_6.alignment = WD_TABLE_ALIGNMENT.CENTER
  1609. # # 提取结果表中数据
  1610. # # 写入数据 土壤质地类型不一致的数据提取出来
  1611. # for i, row in enumerate(table_6.rows):
  1612. # for j, cell in enumerate(row.cells):
  1613. # # 获取单元格中的段落对象
  1614. # paragraph = cell.paragraphs[0]
  1615. # if i == 0:
  1616. # r = paragraph.add_run(str(table_6_data.columns[j]))
  1617. # r.font.bold = True
  1618. # else:
  1619. # r = paragraph.add_run(str(table_6_data.iloc[i - 1, j]))
  1620. # paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  1621. # paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  1622. # paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  1623. # r.font.size = Pt(10.5)
  1624. # r.font.name = 'Times New Roman'
  1625. # r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  1626. doc.add_heading('三、数据合理性审核', level=1)
  1627. long_text4 = """
  1628. 明确数据审核原则,结合外业调查采样,获取的成土环境、土壤利用现状等信息对结果进行综合评价。通过阈值分析、关联分析、逻辑分析等方法对数据准确性进行判断。
  1629. 阈值法(国家和省级数据阈值):结合区域历史数据建立阈值,平台利用阈值法(国家和省级数据值)自动对检测数据进行初步审核,并对超出阈值范围数据做出警示标识,专家或专业技术人员结合区域实际、专家经验判定异常值并对异常数据进行驳回。超出阈值颜色标注。
  1630. 红色: 超出国家阈值,维持试点期间的标红。
  1631. 黄色: 省级阈值在国家阈值范围内的,数据超出省级阈值标黄。
  1632. 紫色: 省级阈值超出国家阈值的,数据超出省级阈值标成紫色(注,此种情况超国家阈值的红色服从紫色,仅标紫色)
  1633. 极值法: 常用的统计量是均值、标准差、最大值、最小值、分位数等,用来判断是否超出了合理的极值范围。根据相关指标历年数据与指标最大值、最小值、平均数、中位数和极差进行审查,结合相关外业情况。
  1634. 关联分析方法: 存在量化关系的指标,通过设定组合筛选异常值,如碳氮比等关联分析。
  1635. 指标综合分析:根据指标相互之间的关系,如有效磷在全磷中的占比、全钾与速效钾缓效钾之和的关系等。有机质、全磷、有效磷、全钾等数据异常; 全氮和有机质之间关系不合理; 速效钾含量远大于缓效钾,盐基总量远大于阳离子交换量; 部分样品阳离子交换量和交换性盐基总量测定结果偏低; 水溶盐离子总量与全盐量的相对偏差已远超过方法规定的允差范围; 容重检测偏差比较大;水稳性大团聚体土壤干燥结块,影响测定结果、重金属按照风险筛选值和风险管控值等问题。
  1636. 数据质量溯源:异常数据溯源,可能是内业测试化验环节问题,也有可能是外业调查采样问题,要结合数据检测和异常复检情况具体判断。
  1637. """
  1638. para = doc.add_paragraph(long_text4)
  1639. run1 = para.runs[0]
  1640. run1.font.name = '宋体' # 设置字体为宋体
  1641. run1.font.size = Pt(11) # 设置字号为11磅
  1642. doc.add_heading('1、阈值法审核', level=2)
  1643. # 插入表格
  1644. paragraph_7 = doc.add_paragraph()
  1645. paragraph_7.add_run(f'表6:{areaName}土壤检测数据超阈值样品统计表').bold = True
  1646. # table_7 = doc.add_table(rows=2, cols=2)
  1647. # paragraph_7.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1648. # table_7.alignment = WD_TABLE_ALIGNMENT.CENTER
  1649. # 写入数据 点击查看数据 这里也不一定写的下 最好是嵌入链接
  1650. doc.add_heading('为避免数据量过多无法显示,请至数据保存文件夹中查看数据表:数据审核过程存疑数据一览表.xlsx', level=4)
  1651. # todo 合并所有数据 审核结果不为空的数据 写入表格保存到指定文件夹
  1652. doc.add_heading('2、极值法审核', level=2)
  1653. doc.add_heading('(1)pH', level=3)
  1654. # 插入ph分布图
  1655. if os.path.isfile(f'{mkdir_path}/PH值分布图.png'):
  1656. doc.add_picture(f'{mkdir_path}/PH值分布图.png', width=Inches(6.0))
  1657. paragraph_t_1 = doc.add_paragraph()
  1658. paragraph_t_1.add_run(f'图1:pH值分布情况').bold = True
  1659. paragraph_t_1.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1660. # 插入频度统计表
  1661. paragraph_8 = doc.add_paragraph()
  1662. paragraph_8.add_run('表7:pH数据统计表').bold = True
  1663. table_8 = doc.add_table(rows=6, cols=2, style='Light Shading Accent 1')
  1664. t_8 = table_8_data['频度分析']
  1665. t_8 = t_8.reset_index()
  1666. t_8.columns = ['指标', '数据']
  1667. paragraph_8.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1668. table_8.alignment = WD_TABLE_ALIGNMENT.CENTER
  1669. for i, row in enumerate(table_8.rows):
  1670. for j, cell in enumerate(row.cells):
  1671. # 获取单元格中的段落对象
  1672. paragraph = cell.paragraphs[0]
  1673. if i == 0:
  1674. r = paragraph.add_run(str(t_8.columns[j]))
  1675. r.font.bold = True
  1676. else:
  1677. r = paragraph.add_run(str(t_8.iloc[i - 1, j]))
  1678. r.font.size = Pt(10.5)
  1679. r.font.name = 'Times New Roman'
  1680. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  1681. paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  1682. paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  1683. paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  1684. # 插入异常数据提取表格 todo 这里数据多的话也可能写不下 最好是嵌入一下
  1685. if not table_8_data['异常数据'].empty:
  1686. paragraph_9 = doc.add_paragraph()
  1687. paragraph_9.add_run('表8:pH异常数据统计表').bold = True
  1688. table_9 = doc.add_table(rows=len(table_8_data['异常数据']) + 1, cols=6, style='Light Shading Accent 1')
  1689. t_9 = table_8_data['异常数据']
  1690. paragraph_9.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1691. table_9.alignment = WD_TABLE_ALIGNMENT.CENTER
  1692. for i, row in enumerate(table_9.rows):
  1693. for j, cell in enumerate(row.cells):
  1694. # 获取单元格中的段落对象
  1695. paragraph = cell.paragraphs[0]
  1696. if i == 0:
  1697. r = paragraph.add_run(str(t_9.columns[j]))
  1698. r.font.bold = True
  1699. else:
  1700. r = paragraph.add_run(str(t_9.iloc[i - 1, j]))
  1701. r.font.size = Pt(10.5)
  1702. r.font.name = 'Times New Roman'
  1703. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  1704. paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  1705. paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  1706. paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  1707. doc.add_heading('3、指标综合分析', level=2)
  1708. # 阳离子交换量与交换性盐总量关系
  1709. if os.path.isfile(f'{mkdir_path}/阳离子交换量与交换性盐基总量相关关系.png'):
  1710. doc.add_picture(f'{mkdir_path}/阳离子交换量与交换性盐基总量相关关系.png', width=Inches(6.0))
  1711. paragraph_t_8 = doc.add_paragraph()
  1712. paragraph_t_8.add_run(f'图8:阳离子交换量与交换性盐总量关系图').bold = True
  1713. paragraph_t_8.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1714. # 交换性盐总量与交换性盐相关关系
  1715. if os.path.isfile(f'{mkdir_path}/交换性盐基总量与交换性盐相关关系(pH小于等于7.5).png'):
  1716. doc.add_picture(f'{mkdir_path}/交换性盐基总量与交换性盐相关关系(pH小于等于7.5).png', width=Inches(6.0))
  1717. paragraph_t_9 = doc.add_paragraph()
  1718. paragraph_t_9.add_run(f'图9:交换性盐基总量和交换性钙镁钠钾分项指标关系(pH≤7.5)').bold = True
  1719. paragraph_t_9.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1720. if os.path.isfile(f'{mkdir_path}/交换性盐基总量与交换性盐相关关系(pH大于7.5).png'):
  1721. doc.add_picture(f'{mkdir_path}/交换性盐基总量与交换性盐相关关系(pH大于7.5).png', width=Inches(6.0))
  1722. paragraph_t_10 = doc.add_paragraph()
  1723. paragraph_t_10.add_run(f'图10:交换性盐基总量和交换性钙镁钠钾分项指标关系(pH大于7.5)').bold = True
  1724. paragraph_t_10.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1725. # 水溶性盐、电导率、离子总量
  1726. if os.path.isfile(f'{mkdir_path}/全盐量分布图.png'):
  1727. doc.add_picture(f'{mkdir_path}/全盐量分布图.png', width=Inches(6.0))
  1728. paragraph_t_11 = doc.add_paragraph()
  1729. paragraph_t_11.add_run(f'图11:全盐量分布图').bold = True
  1730. paragraph_t_11.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1731. if os.path.isfile(f'{mkdir_path}/全盐量与电导率相关性散点图.png'):
  1732. doc.add_picture(f'{mkdir_path}/全盐量与电导率相关性散点图.png', width=Inches(6.0))
  1733. paragraph_t_12 = doc.add_paragraph()
  1734. paragraph_t_12.add_run(f'图12:全盐量与电导率相关性散点图').bold = True
  1735. paragraph_t_12.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1736. if os.path.isfile(f'{mkdir_path}/离子总量与全盐量关系图.png'):
  1737. doc.add_picture(f'{mkdir_path}/离子总量与全盐量关系图.png', width=Inches(6.0))
  1738. paragraph_t_13 = doc.add_paragraph()
  1739. paragraph_t_13.add_run(f'图13:离子总量与全盐量关系图').bold = True
  1740. paragraph_t_13.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1741. # 这里添加新增的剖面数据指标 添加异常数据表和折线图
  1742. # if not errObj['errData'].empty:
  1743. # errData = errObj['errData']
  1744. # errName = errObj['errName']
  1745. # errName.insert(0, '原样品编号')
  1746. # paragraph_12 = doc.add_paragraph()
  1747. # paragraph_12.add_run('表9:有效态元素异常样品统计表').bold = True
  1748. # table_12 = doc.add_table(rows=len(errData)+1, cols=len(errName), style='Light Shading Accent 1')
  1749. # paragraph_12.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1750. # table_12.alignment = WD_TABLE_ALIGNMENT.CENTER
  1751. # for i, row in enumerate(table_12.rows):
  1752. # for j, cell in enumerate(row.cells):
  1753. # # 获取单元格中的段落对象
  1754. # paragraph = cell.paragraphs[0]
  1755. # if i == 0:
  1756. # r = paragraph.add_run(str(errData[errName].columns[j]))
  1757. # r.font.bold = True
  1758. # else:
  1759. # r=paragraph.add_run(str(errData[errName].iloc[i-1, j]))
  1760. #
  1761. # r.font.size = Pt(10.5)
  1762. # r.font.name = 'Times New Roman'
  1763. # r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  1764. # paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  1765. # paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  1766. # paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  1767. # else:
  1768. # paragraph_12 = doc.add_paragraph()
  1769. # paragraph_12.add_run('表9:有效态元素异常样品统计表').bold = True
  1770. # paragraph_12_info = doc.add_paragraph()
  1771. # paragraph_12_info.add_run('无异常数据')
  1772. # paragraph_12.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1773. # paragraph_12_info.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1774. # 新增剖面指标 显示异常有效态数据折线图及
  1775. if os.path.isfile(f'{mkdir_path}/有效态指标异常统计图.png'):
  1776. doc.add_picture(f'{mkdir_path}/有效态指标异常统计图.png', width=Inches(6.0))
  1777. paragraph_t_14 = doc.add_paragraph()
  1778. paragraph_t_14.add_run(f'图14:有效态指标异常统计图').bold = True
  1779. paragraph_t_14.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1780. doc.add_heading('四、审核存疑数据', level=1)
  1781. paragraph_12 = doc.add_paragraph()
  1782. paragraph_12.add_run(f'表9:数据审核过程存疑数据一览表').bold = True
  1783. paragraph_12.alignment = WD_ALIGN_PARAGRAPH.CENTER
  1784. doc.add_heading('为避免数据量过多无法显示,请至数据保存文件夹中查看数据表:数据审核过程存疑数据一览表.xlsx', level=4)
  1785. doc.add_heading('五、附表', level=1)
  1786. doc.add_heading('附表1:某区三普样品数量统计表(表层)', level=2)
  1787. # 插入附表1
  1788. table_1_f = doc.add_table(rows=lenNum_1 + 1, cols=3, style='Light Shading Accent 1')
  1789. table_1_f.alignment = WD_TABLE_ALIGNMENT.CENTER
  1790. # 遍历表格 插入数据
  1791. # 遍历表格的所有单元格,并填充内容
  1792. for i, row in enumerate(table_1_f.rows):
  1793. for j, cell in enumerate(row.cells):
  1794. # 获取单元格中的段落对象
  1795. paragraph = cell.paragraphs[0]
  1796. if i == 0:
  1797. r = paragraph.add_run(str(table_1_data.columns[j]))
  1798. r.font.bold = True
  1799. else:
  1800. r = paragraph.add_run(str(table_1_data.iloc[i - 1, j]))
  1801. r.font.size = Pt(10.5)
  1802. r.font.name = 'Times New Roman'
  1803. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  1804. paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  1805. paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  1806. paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  1807. # 合并单元格 合并第3列的第二行和第三行
  1808. if lenNum_1 > 1:
  1809. table_1_f.cell(2, 2).text = ''
  1810. table_1_f.cell(1, 2).merge(table_1_f.cell(2, 2))
  1811. doc.add_heading('附表2:各指标频度分析表', level=2)
  1812. # 插入表格 写入数据
  1813. table_f_2_data = table_f_2_data.replace(np.nan, '')
  1814. makeInfoTable(table_f_2_data, doc)
  1815. # table_f_2 = doc.add_table(rows=len(table_f_2_data) + 1, cols=6, style='Light Shading Accent 1')
  1816. # for i, row in enumerate(table_f_2.rows):
  1817. # for j, cell in enumerate(row.cells):
  1818. # # 获取单元格中的段落对象
  1819. # paragraph = cell.paragraphs[0]
  1820. # if i == 0:
  1821. # r = paragraph.add_run(str(table_f_2_data.columns[j]))
  1822. # r.font.bold = True
  1823. # else:
  1824. # r = paragraph.add_run(str(table_f_2_data.iloc[i - 1, j]))
  1825. # r.font.size = Pt(10.5)
  1826. # r.font.name = 'Times New Roman'
  1827. # r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  1828. # paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  1829. # paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  1830. # paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  1831. # doc.add_heading('为避免数据量过多无法显示,请至数据保存文件夹中查看数据表:频度分析表.xlsx', level=4)
  1832. doc.add_heading('附表3:各指标频度分析图', level=2)
  1833. # 插入频度信息的图形
  1834. if os.path.isfile(f'{mkdir_path}/pH分析图.png'):
  1835. doc.add_picture(f'{mkdir_path}/pH分析图.png', width=Inches(6.0))
  1836. if os.path.isfile(f'{mkdir_path}/电导率分析图.png'):
  1837. doc.add_picture(f'{mkdir_path}/电导率分析图.png', width=Inches(6.0))
  1838. if os.path.isfile(f'{mkdir_path}/交换性钙分析图.png'):
  1839. doc.add_picture(f'{mkdir_path}/交换性钙分析图.png', width=Inches(6.0))
  1840. if os.path.isfile(f'{mkdir_path}/交换性钾分析图.png'):
  1841. doc.add_picture(f'{mkdir_path}/交换性钾分析图.png', width=Inches(6.0))
  1842. if os.path.isfile(f'{mkdir_path}/交换性镁分析图.png'):
  1843. doc.add_picture(f'{mkdir_path}/交换性镁分析图.png', width=Inches(6.0))
  1844. if os.path.isfile(f'{mkdir_path}/交换性钠分析图.png'):
  1845. doc.add_picture(f'{mkdir_path}/交换性钠分析图.png', width=Inches(6.0))
  1846. if os.path.isfile(f'{mkdir_path}/交换性盐基总量分析图.png'):
  1847. doc.add_picture(f'{mkdir_path}/交换性盐基总量分析图.png', width=Inches(6.0))
  1848. if os.path.isfile(f'{mkdir_path}/全盐量分析图.png'):
  1849. doc.add_picture(f'{mkdir_path}/全盐量分析图.png', width=Inches(6.0))
  1850. if os.path.isfile(f'{mkdir_path}/阳离子交换量分析图.png'):
  1851. doc.add_picture(f'{mkdir_path}/阳离子交换量分析图.png', width=Inches(6.0))
  1852. # 新增的剖面指标
  1853. if os.path.isfile(f'{mkdir_path}/全硫分析图.png'):
  1854. doc.add_picture(f'{mkdir_path}/全硫分析图.png', width=Inches(6.0))
  1855. if os.path.isfile(f'{mkdir_path}/全硅分析图.png'):
  1856. doc.add_picture(f'{mkdir_path}/全硅分析图.png', width=Inches(6.0))
  1857. if os.path.isfile(f'{mkdir_path}/全钙分析图.png'):
  1858. doc.add_picture(f'{mkdir_path}/全钙分析图.png', width=Inches(6.0))
  1859. if os.path.isfile(f'{mkdir_path}/全镁分析图.png'):
  1860. doc.add_picture(f'{mkdir_path}/全镁分析图.png', width=Inches(6.0))
  1861. if os.path.isfile(f'{mkdir_path}/全铝分析图.png'):
  1862. doc.add_picture(f'{mkdir_path}/全铝分析图.png', width=Inches(6.0))
  1863. if os.path.isfile(f'{mkdir_path}/全铁分析图.png'):
  1864. doc.add_picture(f'{mkdir_path}/全铁分析图.png', width=Inches(6.0))
  1865. if os.path.isfile(f'{mkdir_path}/全锰分析图.png'):
  1866. doc.add_picture(f'{mkdir_path}/全锰分析图.png', width=Inches(6.0))
  1867. if os.path.isfile(f'{mkdir_path}/全铜分析图.png'):
  1868. doc.add_picture(f'{mkdir_path}/全铜分析图.png', width=Inches(6.0))
  1869. if os.path.isfile(f'{mkdir_path}/全锌分析图.png'):
  1870. doc.add_picture(f'{mkdir_path}/全锌分析图.png', width=Inches(6.0))
  1871. if os.path.isfile(f'{mkdir_path}/全硼分析图.png'):
  1872. doc.add_picture(f'{mkdir_path}/全硼分析图.png', width=Inches(6.0))
  1873. if os.path.isfile(f'{mkdir_path}/全钼分析图.png'):
  1874. doc.add_picture(f'{mkdir_path}/全钼分析图.png', width=Inches(6.0))
  1875. if os.path.isfile(f'{mkdir_path}/全锌分析图.png'):
  1876. doc.add_picture(f'{mkdir_path}/全锌分析图.png', width=Inches(6.0))
  1877. if os.path.isfile(f'{mkdir_path}/碳酸钙分析图.png'):
  1878. doc.add_picture(f'{mkdir_path}/碳酸钙分析图.png', width=Inches(6.0))
  1879. if os.path.isfile(f'{mkdir_path}/游离铁分析图.png'):
  1880. doc.add_picture(f'{mkdir_path}/游离铁分析图.png', width=Inches(6.0))
  1881. doc.add_heading('附表4:数值修约标准', level=2)
  1882. # 读取数据 插入表格 写入数据
  1883. numData = pd.read_excel('./img/数值修约要求.xlsx', sheet_name='Sheet1')
  1884. table_2_f = doc.add_table(rows=len(numData) + 1, cols=2, style='Light Shading Accent 1')
  1885. table_2_f.alignment = WD_TABLE_ALIGNMENT.CENTER
  1886. for i, row in enumerate(table_2_f.rows):
  1887. for j, cell in enumerate(row.cells):
  1888. # 获取单元格中的段落对象
  1889. paragraph = cell.paragraphs[0]
  1890. if i == 0:
  1891. r = paragraph.add_run(str(numData.columns[j]))
  1892. r.font.bold = True
  1893. else:
  1894. r = paragraph.add_run(str(numData.iloc[i - 1, j]))
  1895. r.font.size = Pt(10.5)
  1896. r.font.name = 'Times New Roman'
  1897. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  1898. paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  1899. paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  1900. paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  1901. # 处理样式 遍历所有的段落 修改字体
  1902. # 遍历并打印每个段落的文本
  1903. paragraphs = doc.paragraphs
  1904. for paragraph in paragraphs:
  1905. for run in paragraph.runs:
  1906. run.font.color.rgb = RGBColor(0, 0, 0)
  1907. run.font.name = 'Times New Roman'
  1908. run.font.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  1909. # run.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  1910. # 保存Word文档
  1911. doc.save(f'{mkdir_path}/{areaName}-{type}审核报告.docx')
  1912. # 生成重金属指标审核报告
  1913. def getHeavyMetalIndicators(originData, data, type, changeFileUrl, saveFileUrl, check_1_data,
  1914. check_3_data,
  1915. check_5_data,
  1916. check_8_data, # 样品编号替换为编号
  1917. check_10_data,
  1918. check_12_data,
  1919. check_14_data):
  1920. # 生成报告
  1921. name = os.path.basename(changeFileUrl)
  1922. n = name.split('.')
  1923. areaName = n[0].replace('数据', '')
  1924. # 生成一个新的文件夹用于存放审核报告相关的数据
  1925. nowTime = time.strftime("%Y-%m-%d %H时%M分%S秒", time.localtime())
  1926. dir_name = f'{areaName}-{type}数据审核报告'
  1927. mkdir_path = saveFileUrl + '/' + dir_name + nowTime
  1928. if not os.path.exists(mkdir_path):
  1929. os.mkdir(mkdir_path)
  1930. heavyMetaData = data[indexClassificationList[type]]
  1931. heavyMetaDataNum = originData[indexClassificationList[type]]
  1932. report.getFrequencyImage(heavyMetaData, mkdir_path)
  1933. heavyMetaData['序号'] = data['序号']
  1934. heavyMetaData['原样品编号'] = data['原样品编号']
  1935. heavyMetaData['样品编号'] = data['样品编号']
  1936. heavyMetaData['地理位置'] = data['地理位置']
  1937. heavyMetaData['母质'] = data['母质']
  1938. heavyMetaData['土壤类型'] = data['土壤类型']
  1939. heavyMetaData['土地利用类型'] = data['土地利用类型']
  1940. # heavyMetaData['土壤质地'] = data['土壤质地']
  1941. heavyMetaData['原样品编号'] = heavyMetaData['原样品编号'].astype(str)
  1942. # checkData = pd.read_excel(changeFileUrl, sheet_name='检测方法')
  1943. heavyMetaDataNum['序号'] = originData['序号']
  1944. heavyMetaDataNum['原样品编号'] = originData['原样品编号']
  1945. heavyMetaDataNum['样品编号'] = originData['样品编号']
  1946. heavyMetaDataNum['地理位置'] = originData['地理位置']
  1947. heavyMetaDataNum['母质'] = originData['母质']
  1948. heavyMetaDataNum['土壤类型'] = originData['土壤类型']
  1949. heavyMetaDataNum['土地利用类型'] = originData['土地利用类型']
  1950. # heavyMetaData['土壤质地'] = data['土壤质地']
  1951. heavyMetaDataNum['原样品编号'] = heavyMetaDataNum['原样品编号'].astype(str)
  1952. # 上面这个地址,可以纯递给函数中,用于保存表格和图片
  1953. # 调用函数 开始生成报告相关内容
  1954. # 表1相关数据
  1955. typeData = report.getSimpleNum(heavyMetaData)
  1956. lenNum_1 = len(typeData['sData'])
  1957. lenNum_1_f = len(typeData['allData'])
  1958. table_1_data = pd.DataFrame({
  1959. '类型': typeData['sData'].index,
  1960. '数量': typeData['sData'],
  1961. '合计': [typeData['sData'].sum() for _ in range(lenNum_1)]
  1962. })
  1963. # 表2数据
  1964. table_2_data = report.getDataComplete(heavyMetaData)
  1965. table_2_data = table_2_data.reset_index()
  1966. table_2_data.columns = ['指标名称', '实测数量', '应测数量']
  1967. # 表3数据
  1968. # table_3_data = report.checkMethod(checkData, mkdir_path)
  1969. # 数据修约 表4
  1970. report.getNum(heavyMetaDataNum, mkdir_path)
  1971. # 数据填报项审核 表5
  1972. report.dataReportResult(heavyMetaData, mkdir_path)
  1973. # 表6数据 土壤质地类型不一致
  1974. middData = heavyMetaData[['原样品编号', '样品编号']].astype(str)
  1975. middData['编号'] = middData['原样品编号']
  1976. del middData['原样品编号']
  1977. check_1_data = pd.merge(check_1_data, middData, how='left', on='编号')
  1978. check_1_data = check_1_data.replace(np.nan, '')
  1979. # typeNotSame = check_1_data[check_1_data['土壤质地'] != check_1_data['土壤类型(判断)']]
  1980. # table_6_data = typeNotSame[['编号', '样品编号', '土壤质地', '土壤类型(判断)']]
  1981. allNeedData = pd.DataFrame({})
  1982. allNeedData['原样品编号'] = check_1_data['编号']
  1983. getSimpleDataNumber = pd.merge(allNeedData, heavyMetaData[['原样品编号', '样品编号']], how='left', on="原样品编号")
  1984. allNeedData['样品编号'] = getSimpleDataNumber['样品编号']
  1985. allNeedData['土地利用类型'] = check_1_data['土地利用类型']
  1986. allNeedData['审核结果'] = check_14_data['审核结果']
  1987. allNeedData['外业'] = ['' for _ in range(len(check_1_data))]
  1988. table_7_data = allNeedData[allNeedData['审核结果'] != '']
  1989. del table_7_data['审核结果']
  1990. # 写进表格
  1991. with pd.ExcelWriter(f'{mkdir_path}/超阈值样品统计表.xlsx', engine='openpyxl') as writer:
  1992. table_7_data.to_excel(writer, index=False, sheet_name='超阈值数据')
  1993. # 表8数据
  1994. table_8_data = report.getPHData(heavyMetaData, mkdir_path)
  1995. # 表12数据 重金属超标
  1996. caOverData = pd.merge(check_1_data[['编号', '土地利用类型']], check_14_data[
  1997. ['编号', 'pH', '镉mg/kg', '汞mg/kg', '砷mg/kg', '铅mg/kg', '铬mg/kg', '镍mg/kg', '审核结果']], how='outer',
  1998. on=['编号'])
  1999. caOverData['原样品编号'] = caOverData['编号']
  2000. caOverData = pd.merge(caOverData, heavyMetaData[['原样品编号', '样品编号']], how='left', on='原样品编号')
  2001. first_column = caOverData.pop('样品编号')
  2002. caOverData.insert(0, '样品编号', first_column)
  2003. caOverData_need = caOverData[caOverData['审核结果'] != '']
  2004. # 写进表格
  2005. with pd.ExcelWriter(f'{mkdir_path}/重金属超筛选值情况统计.xlsx', engine='openpyxl') as writer:
  2006. caOverData_need.to_excel(writer, index=False, sheet_name='重金属超筛选值情况统计')
  2007. # 表13 所有存疑数据
  2008. with pd.ExcelWriter(f'{mkdir_path}/数据审核过程存疑数据一览表.xlsx', engine='openpyxl') as writer:
  2009. allNeedData[allNeedData['审核结果'] != ''].to_excel(writer, index=False, sheet_name='存疑数据')
  2010. # 附表: 频度分析图
  2011. # report.getFrequencyImage(heavyMetaData, mkdir_path)
  2012. table_f_2_data = report.getFrequencyInformation(data, mkdir_path)
  2013. # 新建一个文档
  2014. doc = Document()
  2015. # 添加标题
  2016. doc.add_heading(f"{areaName}第三次全国土壤普查重金属指标数据审核报告", level=0)
  2017. # 在文档中添加封面段落
  2018. fm = doc.add_paragraph()
  2019. fm = doc.add_paragraph()
  2020. fm = doc.add_paragraph()
  2021. fm = doc.add_paragraph()
  2022. fm = doc.add_paragraph()
  2023. # 插入图片,设置宽度为6英寸(可根据需求调整)
  2024. run = fm.add_run()
  2025. run.add_picture('img/第三次全国土壤普查img.png', width=Inches(2.26))
  2026. fm.alignment = WD_TABLE_ALIGNMENT.CENTER
  2027. # 在文档中添加封面段落
  2028. fm = doc.add_paragraph()
  2029. fm = doc.add_paragraph()
  2030. fm = doc.add_paragraph()
  2031. fm = doc.add_paragraph()
  2032. fm = doc.add_paragraph()
  2033. fm = doc.add_paragraph()
  2034. # 获取当前日期
  2035. current_date = datetime.now()
  2036. # 将年份和月份转换为中文大写数字
  2037. year = int(current_date.strftime("%Y")) # 转换为整数
  2038. month = int(current_date.strftime("%m")) # 转换为整数
  2039. # 使用 cn2an 将数字转换为中文大写
  2040. year_chinese = number_to_chinese_year(year) # 年份转换
  2041. month_chinese = cn2an.an2cn(month) # 月份转换
  2042. current_date_formatted = f"{year_chinese}年{month_chinese}月"
  2043. # 组合动态文本
  2044. dynamic_text = f"安徽农业大学资源与环境学院\n{current_date_formatted}"
  2045. # 添加文字并居中
  2046. text_paragraph = doc.add_paragraph()
  2047. text_run = text_paragraph.add_run(dynamic_text)
  2048. text_run.font.name = "宋体"
  2049. text_run.font.size = Pt(18)
  2050. text_run.bold = True # 设置字体加粗
  2051. text_paragraph.alignment = 1 # 1 表示居中对齐
  2052. # 正确插入分页符
  2053. doc.add_page_break()
  2054. heading = doc.add_heading('总体概述', level=1)
  2055. heading.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  2056. # 第一段
  2057. long_text1 = f"""
  2058. {areaName}第三次全国土壤普查县级数据审核报告主要通过收集和整理相关数据,并对其进行内业检测数据的完整性、规范性和合理性进行审核,形成存疑样点清单及存疑样点结果判定,最终编制完成数据审核报告,同时提交( )对相关指标进行整改复测。报告整理了( )个表层样品数据(含平行样、质控样)、( )个水稳性大团聚体样品数据(含平行样)、( )个剖面样品数据(含平行样、质控样),共( )次样品检测结果分析情况。相关结果分别按照物理性指标检测数据、一般化学指标检测数据、常规养分指标检测数据和重金属指标检测数据形成四份报告。本报告为表层样常规养分指标检测数据审核报告。
  2059. """
  2060. para0 = doc.add_paragraph(long_text1)
  2061. run0 = para0.runs[0] # 获取段落中的第一个run对象
  2062. run0.font.name = '宋体' # 设置字体为宋体
  2063. run0.font.size = Pt(11) # 设置字号为11磅
  2064. # 设置段落的行间距为1.5倍
  2065. para_format = para0.paragraph_format
  2066. para_format.line_spacing = 1.5 # 设置行间距为1.5倍
  2067. # 添加一级标题
  2068. doc.add_heading('一、数据完整性审核', level=1)
  2069. # 第二段
  2070. long_text2 = """
  2071. 外业信息调查采样环节:采用电子围栏和外业调查采样APP,对采样位置和填报信息进行管理,确保外业调查信息填报完整。
  2072. 样品检测数据上报环节:通过土壤普查工作平台对上报数据的完整性进行筛查。( )第三次土壤普查相关指标检测数据由( )提供,数据均已通过省级质控实验室和县级土壤普查办审核;相关土壤指标历史数据则由( )第三次土壤普查办公室提供。根据《第三次全国土壤普查土壤样品制备与检测技术规范(修订版)》要求,统计各土地利用类型的样品数量,并按照耕地园地土壤样品(表层/剖面)、林地草地土壤样品(表层/剖面)以及水稳定性大团聚体样品(见表1)进行分类,编制了指标名称与实际检测样品数量统计表(见表2),其中水溶性盐分总量大于(),增加检测了八大离子(该指标在化学指标检测数据审核报告内)。
  2073. """
  2074. para = doc.add_paragraph(long_text2)
  2075. run1 = para.runs[0]
  2076. run1.font.name = '宋体' # 设置字体为宋体
  2077. run1.font.size = Pt(11) # 设置字号为11磅
  2078. # 设置段落的行间距为1.5倍
  2079. para_format = para.paragraph_format
  2080. para_format.line_spacing = 1.5 # 设置行间距为1.5倍
  2081. doc.add_heading('1、土地利用类型与检测指标符合性审核', level=2)
  2082. # 插入表格1
  2083. paragraph_1 = doc.add_paragraph()
  2084. paragraph_1.add_run(f"表1:{areaName}三普样品数量统计表(表层)").bold = True
  2085. # 设置居中
  2086. paragraph_1.alignment = WD_ALIGN_PARAGRAPH.CENTER
  2087. table_1 = doc.add_table(rows=lenNum_1 + 1, cols=3, style='Light Shading Accent 1')
  2088. table_1.alignment = WD_TABLE_ALIGNMENT.CENTER
  2089. # 遍历表格 插入数据
  2090. # 遍历表格的所有单元格,并填充内容
  2091. for i, row in enumerate(table_1.rows):
  2092. for j, cell in enumerate(row.cells):
  2093. # 获取单元格中的段落对象
  2094. paragraph = cell.paragraphs[0]
  2095. if i == 0:
  2096. r = paragraph.add_run(str(table_1_data.columns[j]))
  2097. r.font.bold = True
  2098. else:
  2099. r = paragraph.add_run(str(table_1_data.iloc[i - 1, j]))
  2100. r.font.size = Pt(10.5)
  2101. r.font.name = 'Times New Roman'
  2102. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  2103. paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  2104. paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  2105. paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  2106. # 合并单元格 合并第3列的第二行和第三行
  2107. if lenNum_1 > 1:
  2108. table_1.cell(2, 2).text = ''
  2109. table_1.cell(1, 2).merge(table_1.cell(2, 2))
  2110. ############test##############
  2111. doc.add_heading('2、指标名称与实际检测样品数量完整性审核', level=2)
  2112. # 插入表格2
  2113. paragraph_2 = doc.add_paragraph()
  2114. paragraph_2.add_run(f'表2:{areaName}指标名称与实际检测样品数量统计表').bold = True
  2115. table_2 = doc.add_table(rows=len(table_2_data) + 1, cols=3, style='Light Shading Accent 1')
  2116. paragraph_2.alignment = WD_ALIGN_PARAGRAPH.CENTER
  2117. table_2.alignment = WD_TABLE_ALIGNMENT.CENTER
  2118. for i, row in enumerate(table_2.rows):
  2119. for j, cell in enumerate(row.cells):
  2120. # 获取单元格中的段落对象
  2121. paragraph = cell.paragraphs[0]
  2122. if i == 0:
  2123. r = paragraph.add_run(str(table_2_data.columns[j]))
  2124. r.font.bold = True
  2125. else:
  2126. r = paragraph.add_run(str(table_2_data.iloc[i - 1, j]))
  2127. paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  2128. paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  2129. paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  2130. r.font.size = Pt(10.5)
  2131. r.font.name = 'Times New Roman'
  2132. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  2133. doc.add_heading('二、数据规范性审核', level=1)
  2134. long_text3 = """
  2135. 按照《第三次全国土壤普查暂行土壤分类系统 (试行)》、《第三次全国土壤普查工作底图制作与采样点布设技术规范》、《第三次全国土壤普查土壤类型图编制技术规范》《第三次全国土壤普查土壤样品制备与检测技术规范》等规范统一标准和表现形式,土地利用方式按照第三次国土调查土地利用信息统一,种植制度按照农业区划信息进行统一。三普工作平台同时内置指标量纲、数字修约和允差等,控制数据规范性。
  2136. 根据《第三次全国土壤普查土壤样品制备与检测技术规范(修订版)》,对检测指标对应的检测方法与相关标准或规范进行审核,得到检测方法审核、数值修约审核、数据填报项审核结果,未检出项填报以检出限的一半上报并加注*号。根据土壤普查教材中机械组成分类参考表,并进行宁国土壤质地填报审核结果表(见表6)。
  2137. """
  2138. para = doc.add_paragraph(long_text3)
  2139. run1 = para.runs[0]
  2140. run1.font.name = '宋体' # 设置字体为宋体
  2141. run1.font.size = Pt(11) # 设置字号为11磅
  2142. doc.add_heading('1、数据填报规范性审核', level=2)
  2143. # 插入表3
  2144. paragraph_3 = doc.add_paragraph()
  2145. paragraph_3.add_run(f'表3:{areaName}土壤检测数据检测方法填报审核结果表').bold = True
  2146. # table_3 = doc.add_table(rows=2, cols=2)
  2147. paragraph_3.alignment = WD_ALIGN_PARAGRAPH.CENTER
  2148. # table_3.alignment = WD_TABLE_ALIGNMENT.CENTER
  2149. # 写入数据 这里数据写不下 嵌入链接
  2150. doc.add_heading('为避免数据量过多无法显示,请至数据保存文件夹中查看数据表:检测方法审核结果.xlsx', level=4)
  2151. doc.add_heading('2、数值修约规范性审核', level=2)
  2152. # 插入表4
  2153. paragraph_4 = doc.add_paragraph()
  2154. paragraph_4.add_run(f'表4:{areaName}土壤检测数据数值修约结果表').bold = True
  2155. # table_4 = doc.add_table(rows=2, cols=2)
  2156. paragraph_4.alignment = WD_ALIGN_PARAGRAPH.CENTER
  2157. # table_4.alignment = WD_TABLE_ALIGNMENT.CENTER
  2158. doc.add_heading('为避免数据量过多无法显示,请至数据保存文件夹中查看数据表:数值修约审核.xlsx', level=4)
  2159. # 填入数据 这里数据也放不下 嵌入链接
  2160. doc.add_heading('3、数据未检出的填报规范性审核', level=2)
  2161. # 插入表5
  2162. paragraph_5 = doc.add_paragraph()
  2163. paragraph_5.add_run(f'表5:{areaName}土壤检测数据未检出项填报审核结果表').bold = True
  2164. # table_5 = doc.add_table(rows=2, cols=2)
  2165. paragraph_5.alignment = WD_ALIGN_PARAGRAPH.CENTER
  2166. # table_5.alignment = WD_TABLE_ALIGNMENT.CENTER
  2167. # 写入数据 这里数据也放不下 嵌入链接
  2168. doc.add_heading('为避免数据量过多无法显示,请至数据保存文件夹中查看数据表:数据填报项审核结果.xlsx', level=4)
  2169. # doc.add_heading('4、土壤质地填报规范性审核', level=2)
  2170. # # 插入表6
  2171. # paragraph_6 = doc.add_paragraph()
  2172. # paragraph_6.add_run(f'表6:{areaName}土壤质地填报审核结果表').bold = True
  2173. # table_6 = doc.add_table(rows=len(table_6_data) + 1, cols=4, style='Light Shading Accent 1')
  2174. # paragraph_6.alignment = WD_ALIGN_PARAGRAPH.CENTER
  2175. # table_6.alignment = WD_TABLE_ALIGNMENT.CENTER
  2176. # # 提取结果表中数据
  2177. # # 写入数据 土壤质地类型不一致的数据提取出来
  2178. # for i, row in enumerate(table_6.rows):
  2179. # for j, cell in enumerate(row.cells):
  2180. # # 获取单元格中的段落对象
  2181. # paragraph = cell.paragraphs[0]
  2182. # if i == 0:
  2183. # r = paragraph.add_run(str(table_6_data.columns[j]))
  2184. # r.font.bold = True
  2185. # else:
  2186. # r = paragraph.add_run(str(table_6_data.iloc[i - 1, j]))
  2187. # paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  2188. # paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  2189. # paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  2190. # r.font.size = Pt(10.5)
  2191. # r.font.name = 'Times New Roman'
  2192. # r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  2193. doc.add_heading('三、数据合理性审核', level=1)
  2194. long_text4 = """
  2195. 明确数据审核原则,结合外业调查采样,获取的成土环境、土壤利用现状等信息对结果进行综合评价。通过阈值分析、关联分析、逻辑分析等方法对数据准确性进行判断。
  2196. 阈值法(国家和省级数据阈值):结合区域历史数据建立阈值,平台利用阈值法(国家和省级数据值)自动对检测数据进行初步审核,并对超出阈值范围数据做出警示标识,专家或专业技术人员结合区域实际、专家经验判定异常值并对异常数据进行驳回。超出阈值颜色标注。
  2197. 红色: 超出国家阈值,维持试点期间的标红。
  2198. 黄色: 省级阈值在国家阈值范围内的,数据超出省级阈值标黄。
  2199. 紫色: 省级阈值超出国家阈值的,数据超出省级阈值标成紫色(注,此种情况超国家阈值的红色服从紫色,仅标紫色)
  2200. 极值法: 常用的统计量是均值、标准差、最大值、最小值、分位数等,用来判断是否超出了合理的极值范围。根据相关指标历年数据与指标最大值、最小值、平均数、中位数和极差进行审查,结合相关外业情况。
  2201. 关联分析方法: 存在量化关系的指标,通过设定组合筛选异常值,如碳氮比等关联分析。
  2202. 指标综合分析:根据指标相互之间的关系,如有效磷在全磷中的占比、全钾与速效钾缓效钾之和的关系等。有机质、全磷、有效磷、全钾等数据异常; 全氮和有机质之间关系不合理; 速效钾含量远大于缓效钾,盐基总量远大于阳离子交换量; 部分样品阳离子交换量和交换性盐基总量测定结果偏低; 水溶盐离子总量与全盐量的相对偏差已远超过方法规定的允差范围; 容重检测偏差比较大;水稳性大团聚体土壤干燥结块,影响测定结果、重金属按照风险筛选值和风险管控值等问题。
  2203. 数据质量溯源:异常数据溯源,可能是内业测试化验环节问题,也有可能是外业调查采样问题,要结合数据检测和异常复检情况具体判断。
  2204. """
  2205. para = doc.add_paragraph(long_text4)
  2206. run1 = para.runs[0]
  2207. run1.font.name = '宋体' # 设置字体为宋体
  2208. run1.font.size = Pt(11) # 设置字号为11磅
  2209. doc.add_heading('1、阈值法审核', level=2)
  2210. # 插入表格
  2211. paragraph_7 = doc.add_paragraph()
  2212. paragraph_7.add_run(f'表6:{areaName}土壤检测数据超阈值样品统计表').bold = True
  2213. # table_7 = doc.add_table(rows=2, cols=2)
  2214. # paragraph_7.alignment = WD_ALIGN_PARAGRAPH.CENTER
  2215. # table_7.alignment = WD_TABLE_ALIGNMENT.CENTER
  2216. # 写入数据 点击查看数据 这里也不一定写的下 最好是嵌入链接
  2217. doc.add_heading('为避免数据量过多无法显示,请至数据保存文件夹中查看数据表:数据审核过程存疑数据一览表.xlsx', level=4)
  2218. # todo 合并所有数据 审核结果不为空的数据 写入表格保存到指定文件夹
  2219. doc.add_heading('2、极值法审核', level=2)
  2220. doc.add_heading('(1)pH', level=3)
  2221. # 插入ph分布图
  2222. if os.path.isfile(f'{mkdir_path}/pH值分布图.png'):
  2223. doc.add_picture(f'{mkdir_path}/pH值分布图.png', width=Inches(6.0))
  2224. paragraph_t_1 = doc.add_paragraph()
  2225. paragraph_t_1.add_run(f'图1:pH值分布情况').bold = True
  2226. paragraph_t_1.alignment = WD_ALIGN_PARAGRAPH.CENTER
  2227. # 插入频度统计表
  2228. paragraph_8 = doc.add_paragraph()
  2229. paragraph_8.add_run('表7:pH数据统计表').bold = True
  2230. table_8 = doc.add_table(rows=6, cols=2, style='Light Shading Accent 1')
  2231. t_8 = table_8_data['频度分析']
  2232. t_8 = t_8.reset_index()
  2233. t_8.columns = ['指标', '数据']
  2234. paragraph_8.alignment = WD_ALIGN_PARAGRAPH.CENTER
  2235. table_8.alignment = WD_TABLE_ALIGNMENT.CENTER
  2236. for i, row in enumerate(table_8.rows):
  2237. for j, cell in enumerate(row.cells):
  2238. # 获取单元格中的段落对象
  2239. paragraph = cell.paragraphs[0]
  2240. if i == 0:
  2241. r = paragraph.add_run(str(t_8.columns[j]))
  2242. r.font.bold = True
  2243. else:
  2244. r = paragraph.add_run(str(t_8.iloc[i - 1, j]))
  2245. r.font.size = Pt(10.5)
  2246. r.font.name = 'Times New Roman'
  2247. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  2248. paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  2249. paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  2250. paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  2251. # 插入异常数据提取表格 todo 这里数据多的话也可能写不下 最好是嵌入一下
  2252. if not table_8_data['异常数据'].empty:
  2253. paragraph_9 = doc.add_paragraph()
  2254. paragraph_9.add_run('表8:pH异常数据统计表').bold = True
  2255. table_9 = doc.add_table(rows=len(table_8_data['异常数据']) + 1, cols=6, style='Light Shading Accent 1')
  2256. t_9 = table_8_data['异常数据']
  2257. paragraph_9.alignment = WD_ALIGN_PARAGRAPH.CENTER
  2258. table_9.alignment = WD_TABLE_ALIGNMENT.CENTER
  2259. for i, row in enumerate(table_9.rows):
  2260. for j, cell in enumerate(row.cells):
  2261. # 获取单元格中的段落对象
  2262. paragraph = cell.paragraphs[0]
  2263. if i == 0:
  2264. r = paragraph.add_run(str(t_9.columns[j]))
  2265. r.font.bold = True
  2266. else:
  2267. r = paragraph.add_run(str(t_9.iloc[i - 1, j]))
  2268. r.font.size = Pt(10.5)
  2269. r.font.name = 'Times New Roman'
  2270. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  2271. paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  2272. paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  2273. paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  2274. doc.add_heading('4、指标综合分析', level=2)
  2275. doc.add_heading('表9:重金属超筛选值情况统计', level=4)
  2276. # todo 获取重金属数据
  2277. doc.add_heading('四、审核存疑数据', level=1)
  2278. paragraph_12 = doc.add_paragraph()
  2279. paragraph_12.add_run(f'表10:数据审核过程存疑数据一览表').bold = True
  2280. paragraph_12.alignment = WD_ALIGN_PARAGRAPH.CENTER
  2281. doc.add_heading('为避免数据量过多无法显示,请至数据保存文件夹中查看数据表:数据审核过程存疑数据一览表.xlsx', level=4)
  2282. doc.add_heading('五、附表', level=1)
  2283. doc.add_heading('附表1:某区三普样品数量统计表(表层)', level=2)
  2284. # 插入附表1
  2285. table_1_f = doc.add_table(rows=lenNum_1 + 1, cols=3, style='Light Shading Accent 1')
  2286. table_1_f.alignment = WD_TABLE_ALIGNMENT.CENTER
  2287. # 遍历表格 插入数据
  2288. # 遍历表格的所有单元格,并填充内容
  2289. for i, row in enumerate(table_1_f.rows):
  2290. for j, cell in enumerate(row.cells):
  2291. # 获取单元格中的段落对象
  2292. paragraph = cell.paragraphs[0]
  2293. if i == 0:
  2294. r = paragraph.add_run(str(table_1_data.columns[j]))
  2295. r.font.bold = True
  2296. else:
  2297. r = paragraph.add_run(str(table_1_data.iloc[i - 1, j]))
  2298. r.font.size = Pt(10.5)
  2299. r.font.name = 'Times New Roman'
  2300. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  2301. paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  2302. paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  2303. paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  2304. # 合并单元格 合并第3列的第二行和第三行
  2305. if lenNum_1 > 1:
  2306. table_1_f.cell(2, 2).text = ''
  2307. table_1_f.cell(1, 2).merge(table_1_f.cell(2, 2))
  2308. doc.add_heading('附表2:各指标频度分析表', level=2)
  2309. # 插入表格 写入数据
  2310. table_f_2_data = table_f_2_data.replace(np.nan, '')
  2311. makeInfoTable(table_f_2_data, doc)
  2312. # table_f_2 = doc.add_table(rows=len(table_f_2_data) + 1, cols=6, style='Light Shading Accent 1')
  2313. # for i, row in enumerate(table_f_2.rows):
  2314. # for j, cell in enumerate(row.cells):
  2315. # # 获取单元格中的段落对象
  2316. # paragraph = cell.paragraphs[0]
  2317. # if i == 0:
  2318. # r = paragraph.add_run(str(table_f_2_data.columns[j]))
  2319. # r.font.bold = True
  2320. # else:
  2321. # r = paragraph.add_run(str(table_f_2_data.iloc[i - 1, j]))
  2322. # r.font.size = Pt(10.5)
  2323. # r.font.name = 'Times New Roman'
  2324. # r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  2325. # paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  2326. # paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  2327. # paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  2328. # doc.add_heading('为避免数据量过多无法显示,请至数据保存文件夹中查看数据表:频度分析表.xlsx', level=4)
  2329. doc.add_heading('附表3:各指标频度分析图', level=2)
  2330. # 插入频度信息的图形
  2331. if os.path.isfile(f'{mkdir_path}/pH分析图.png'):
  2332. doc.add_picture(f'{mkdir_path}/pH分析图.png', width=Inches(6.0))
  2333. if os.path.isfile(f'{mkdir_path}/总镉分析图.png'):
  2334. doc.add_picture(f'{mkdir_path}/总镉分析图.png', width=Inches(6.0))
  2335. if os.path.isfile(f'{mkdir_path}/总铬分析图.png'):
  2336. doc.add_picture(f'{mkdir_path}/总铬分析图.png', width=Inches(6.0))
  2337. if os.path.isfile(f'{mkdir_path}/总汞分析图.png'):
  2338. doc.add_picture(f'{mkdir_path}/总汞分析图.png', width=Inches(6.0))
  2339. if os.path.isfile(f'{mkdir_path}/总镍分析图.png'):
  2340. doc.add_picture(f'{mkdir_path}/总镍分析图.png', width=Inches(6.0))
  2341. if os.path.isfile(f'{mkdir_path}/总砷分析图.png'):
  2342. doc.add_picture(f'{mkdir_path}/总砷分析图.png', width=Inches(6.0))
  2343. if os.path.isfile(f'{mkdir_path}/总铅分析图.png'):
  2344. doc.add_picture(f'{mkdir_path}/总铅分析图.png', width=Inches(6.0))
  2345. doc.add_heading('附表4:数值修约标准', level=2)
  2346. # 读取数据 插入表格 写入数据
  2347. numData = pd.read_excel('./img/数值修约要求.xlsx', sheet_name='Sheet1')
  2348. table_2_f = doc.add_table(rows=len(numData) + 1, cols=2, style='Light Shading Accent 1')
  2349. table_2_f.alignment = WD_TABLE_ALIGNMENT.CENTER
  2350. for i, row in enumerate(table_2_f.rows):
  2351. for j, cell in enumerate(row.cells):
  2352. # 获取单元格中的段落对象
  2353. paragraph = cell.paragraphs[0]
  2354. if i == 0:
  2355. r = paragraph.add_run(str(numData.columns[j]))
  2356. r.font.bold = True
  2357. else:
  2358. r = paragraph.add_run(str(numData.iloc[i - 1, j]))
  2359. r.font.size = Pt(10.5)
  2360. r.font.name = 'Times New Roman'
  2361. r.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  2362. paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
  2363. paragraph.paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER # 对齐
  2364. paragraph.paragraph_format.line_spacing = 1 # 段落行间距
  2365. # 处理样式 遍历所有的段落 修改字体
  2366. # 遍历并打印每个段落的文本
  2367. paragraphs = doc.paragraphs
  2368. for paragraph in paragraphs:
  2369. for run in paragraph.runs:
  2370. run.font.color.rgb = RGBColor(0, 0, 0)
  2371. run.font.name = 'Times New Roman'
  2372. run.font.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  2373. # run.element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312')
  2374. # 保存Word文档
  2375. doc.save(f'{mkdir_path}/{areaName}-{type}审核报告.docx')
  2376. def number_to_chinese_year(number):
  2377. # 定义数字到中文大写的映射
  2378. chinese_numerals = {'0': '〇', '1': '一', '2': '二', '3': '三',
  2379. '4': '四', '5': '五', '6': '六', '7': '七',
  2380. '8': '八', '9': '九'}
  2381. # 将数字逐个字符转换为中文大写
  2382. return ''.join(chinese_numerals[digit] for digit in str(number))