partReport.py 139 KB

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