diff --git a/scripts/generate.py b/scripts/generate.py index 059eb1c..e98d0c7 100644 --- a/scripts/generate.py +++ b/scripts/generate.py @@ -1,27 +1,25 @@ #!/usr/bin/env python3 """ -土地平整工程竣工结算资料(部分)生成 -从单项工程结算表中提取数据,生成T3田块竣工结算资料套表。 +土地平整工程竣工结算资料(部分)生成 v2.0 +从用户提供的工程量结算前后对比表中提取水浇地15~25°区域各田块数据, +生成分部工程工程量汇总表及各田块竣工结算资料套表。 """ import sys import json import os import re -from copy import copy -# ── helpers for openpyxl ────────────────────────────────────────────── try: import openpyxl from openpyxl.styles import ( - Font, Border, Side, Alignment, PatternFill, NamedStyle + Font, Border, Side, Alignment, PatternFill ) from openpyxl.utils import get_column_letter except ImportError: - print(json.dumps({"error": "openpyxl 未安装,请在环境安装: pip install openpyxl"})) + print(json.dumps({"error": "openpyxl 未安装"})) sys.exit(1) -# ── also try xlrd for .xls input ────────────────────────────────────── try: import xlrd HAS_XLRD = True @@ -33,514 +31,518 @@ except ImportError: # Style definitions # ══════════════════════════════════════════════════════════════════════ -THIN_BORDER = Border( - left=Side(style='thin'), - right=Side(style='thin'), - top=Side(style='thin'), - bottom=Side(style='thin'), -) - -NO_BORDER = Border() - +THIN = Border(left=Side('thin'), right=Side('thin'), + top=Side('thin'), bottom=Side('thin')) TITLE_FONT = Font(name='宋体', size=16, bold=True) HEADER_FONT = Font(name='宋体', size=10, bold=True) -NORMAL_FONT = Font(name='宋体', size=10) -SIGN_FONT = Font(name='宋体', size=10, bold=True) -SMALL_FONT = Font(name='宋体', size=9) - -CENTER_ALIGN = Alignment(horizontal='center', vertical='center', wrap_text=True) -LEFT_ALIGN = Alignment(horizontal='left', vertical='center', wrap_text=True) -LEFT_TOP = Alignment(horizontal='left', vertical='top', wrap_text=True) - -HEADER_FILL = PatternFill(start_color='D9E2F3', end_color='D9E2F3', fill_type='solid') -LIGHT_YELLOW = PatternFill(start_color='FFF2CC', end_color='FFF2CC', fill_type='solid') +NORMAL = Font(name='宋体', size=10) +BOLD = Font(name='宋体', size=10, bold=True) +SMALL = Font(name='宋体', size=9) +CA = Alignment(horizontal='center', vertical='center', wrap_text=True) +LA = Alignment(horizontal='left', vertical='center', wrap_text=True) +HDR_FILL = PatternFill(start_color='D9E2F3', end_color='D9E2F3', fill_type='solid') -def apply_cell(ws, row, col, value, font=None, alignment=None, border=None, fill=None, number_format=None): - """Helper to set a cell value + style.""" - cell = ws.cell(row=row, column=col, value=value) - if font: - cell.font = font - if alignment: - cell.alignment = alignment - if border: - cell.border = border - if fill: - cell.fill = fill - if number_format: - cell.number_format = number_format +def ac(ws, r, c, v, font=None, align=None, border=None, fill=None, nf=None): + """Set cell value + style.""" + cell = ws.cell(row=r, column=c, value=v) + if font: cell.font = font + if align: cell.alignment = align + if border: cell.border = border + if fill: cell.fill = fill + if nf: cell.number_format = nf return cell -def merge_and_set(ws, r1, r2, c1, c2, value, font=None, alignment=None, border=None, fill=None): - """Merge cells and set value + style in the top-left cell.""" +def ms(ws, r1, r2, c1, c2, v, font=None, align=None, border=None, fill=None): + """Merge + set.""" ws.merge_cells(start_row=r1, start_column=c1, end_row=r2, end_column=c2) - return apply_cell(ws, r1, c1, value, font=font, alignment=alignment, border=border, fill=fill) + return ac(ws, r1, c1, v, font=font, align=align, border=border, fill=fill) -def thin_border_range(ws, r1, r2, c1, c2): - """Apply thin border to all cells in range.""" - for r in range(r1, r2 + 1): - for c in range(c1, c2 + 1): - ws.cell(row=r, column=c).border = THIN_BORDER +def cw(ws, widths): + for ci, w in widths.items(): + ws.column_dimensions[get_column_letter(ci)].width = w -def set_col_widths(ws, widths): - """Set column widths: widths is a dict {col_index: width_in_chars} (1-based)""" - for col_idx, w in widths.items(): - ws.column_dimensions[get_column_letter(col_idx)].width = w - - -def set_row_heights(ws, heights): - """Set row heights: heights is a dict {row_index: height_in_points} (1-based)""" - for row_idx, h in heights.items(): - ws.row_dimensions[row_idx].height = h +def rh(ws, heights): + for ri, h in heights.items(): + ws.row_dimensions[ri].height = h # ══════════════════════════════════════════════════════════════════════ -# Input reader +# Input parser — 鸡噜工程量结算前后对比表.xlsx # ══════════════════════════════════════════════════════════════════════ -def read_input(input_path): +def parse_input(input_path): """ - Read the 单项工程结算表 and return a dict with: + Read the 鸡噜工程量结算前后对比表.xlsx (sheet '土地平整工程'). + Extract: - project_name - - contractor - - quantities: { '清理表土': float, '修平田地': float, '田埂修筑': float } - - date_value (if available) + - fields: [{'name':'T3', 'area':2.5638, '清理表土':7662.75, '修平田地':4807.15, '田埂修筑':86.66}, ...] + Only parses section (一) 水浇地15~25°区域. """ + result = {'project_name': '', 'fields': []} + ext = os.path.splitext(input_path)[1].lower() - result = { - 'project_name': '', - 'contractor': '', - 'contract_section': '', - 'quantities': {}, - 'date_value': None, - } - - if ext in ('.xls',): + if ext == '.xls': if not HAS_XLRD: - raise RuntimeError( - "输入文件为 .xls 格式,但环境未安装 xlrd 库。" - "请将文件另存为 .xlsx 格式后重试。" - ) + raise RuntimeError("需安装 xlrd 以读取 .xls 文件") wb = xlrd.open_workbook(input_path) - ws = wb.sheet_by_index(0) - # Row 0: title - # Row 1: project name (col 1) - # Row 2: contractor (col 1) - # Row 3: header row - # Row 4-8: process rows - result['project_name'] = str(ws.cell(1, 1).value or '') - result['contractor'] = str(ws.cell(2, 1).value or '') - # 合同段 at (1, 8) - result['contract_section'] = str(ws.cell(1, 9).value or '') - # Quantity cell: col 8 (0-indexed) in rows 4,5,6 - process_map = { - '清理表土': (4, 9), - '修平田地': (5, 9), - '田埂修筑': (6, 9), - } - for pname, (r, c) in process_map.items(): - cv = ws.cell(r, c).value - try: - result['quantities'][pname] = float(cv) if cv else 0.0 - except (ValueError, TypeError): - result['quantities'][pname] = 0.0 - # Date - for r in range(ws.nrows): - for c in range(ws.ncols): - if ws.cell(r, c).ctype == 3: - dt = xlrd.xldate_as_tuple(ws.cell(r, c).value, wb.datemode) - result['date_value'] = dt - break - if result['date_value']: - break - - elif ext in ('.xlsx',): + ws = wb.sheet_by_index(0) # assumes first sheet + elif ext == '.xlsx': wb = openpyxl.load_workbook(input_path, data_only=True) - ws = wb.active - result['project_name'] = str(ws.cell(2, 2).value or '') - result['contractor'] = str(ws.cell(3, 2).value or '') - result['contract_section'] = str(ws.cell(2, 10).value or '') - process_map = { - '清理表土': (5, 10), - '修平田地': (6, 10), - '田埂修筑': (7, 10), - } - for pname, (r, c) in process_map.items(): - cv = ws.cell(r, c).value - try: - result['quantities'][pname] = float(cv) if cv else 0.0 - except (ValueError, TypeError): - result['quantities'][pname] = 0.0 + # Find the right sheet + sheet_name = None + for sn in ('土地平整工程', wb.sheetnames[0]): + if sn in wb.sheetnames: + sheet_name = sn + break + if not sheet_name: + sheet_name = wb.sheetnames[0] + ws = wb[sheet_name] else: - raise ValueError(f"不支持的文件格式: {ext},请提供 .xls 或 .xlsx 文件") + raise ValueError(f"不支持的文件格式: {ext}") + + # Extract project name from row 2 + if ext == '.xls': + raw = str(ws.cell(1, 0).value or '') # cell A2: 项目名称:xxx + else: + raw = str(ws.cell(2, 1).value or '') # cell A2: 项目名称:xxx + m = re.search(r'项目名称[::]\s*(.+)', raw) + if m: + result['project_name'] = m.group(1).strip() + else: + result['project_name'] = raw + + # Now parse each field — find section (一) 水浇地15~25°区域 + # Then read subsequent rows: field blocks (number + sub-rows for 3 processes) + # Data structure in the spreadsheet: + # 编号 | 项目名称 | 单位 | 工程量(原) | 单价 | 合价 | ... + # (一) | 水浇地15~25°区域 | hm² | 40.2677 | ... + # 1 | T3 | hm² | 2.5638 | ... + # (1) | 清理表土 | m³ | 7662.75 | ... + # (2) | 修平田地 | m³ | 4807.15 | ... + # (3) | 田埂修筑 | m³ | 86.66 | ... + # 2 | T4 | hm² | ... + # ... + + def cell_val(r, c): + if ext == '.xls': + v = ws.cell(r, c).value + return str(v) if v is not None else '' + else: + v = ws.cell(r, c).value + return str(v) if v is not None else '' + + def cell_num(r, c, default=0.0): + if ext == '.xls': + v = ws.cell(r, c).value + else: + v = ws.cell(r, c).value + try: + return float(v) + except (ValueError, TypeError): + return default + + max_row = ws.nrows if ext == '.xls' else ws.max_row + + # Find start: (一) row + start_row = None + for r in range(1, max_row + 1 if ext == '.xls' else max_row + 1): + rid = cell_val(r, 0 if ext == '.xls' else 1).strip() + name = cell_val(r, 1 if ext == '.xls' else 2).strip() + if '水浇地' in name and '15' in name: + start_row = r + break + + if start_row is None: + raise ValueError("未找到'水浇地15~25°区域'段落") + + # Parse fields: look for numeric IDs followed by (1)/(2)/(3) process rows + current_field = None + for r in range(start_row + 1 if ext == '.xls' else start_row + 1, max_row + 1): + rid = cell_val(r, 0 if ext == '.xls' else 1).strip() + name = cell_val(r, 1 if ext == '.xls' else 2).strip() + unit = cell_val(r, 2 if ext == '.xls' else 3).strip() + + # Stop at next section (二) + if '(二)' in rid or ('水田' in name and '6' in name): + break + # Skip section header row itself + if '(一)' in rid: + continue + + # It's a process sub-row + if rid in ('(1)', '(2)', '(3)') and current_field: + proc_name = name + qty = cell_num(r, 3 if ext == '.xls' else 4) + if proc_name in ('清理表土', '修平田地', '田埂修筑'): + current_field[proc_name] = qty + continue + + # It's a field row (number + field name) + try: + int(rid) # numeric id = field row + except ValueError: + # Not a field row, skip + continue + + area = cell_num(r, 3 if ext == '.xls' else 4) + field_name_raw = name.strip() + # Extract the core field name (e.g., "T3" from "T3" or "T3田块") + field_name = field_name_raw + # Save current field + current_field = { + 'name': field_name, + 'area': area, + 'field_display': f'{field_name}田块', + '清理表土': 0, + '修平田地': 0, + '田埂修筑': 0, + } + result['fields'].append(current_field) return result # ══════════════════════════════════════════════════════════════════════ -# Output document generators +# Output: 分部工程工程量汇总表 # ══════════════════════════════════════════════════════════════════════ -def generate_report_form(wb, data, params): +def generate_subitem_summary(wb, data, params): """ - 输出文件1:计量报验单 - 文件名: 01_{field_name}单元工程计量报验单.xlsx - Template: 3.3.3-01.01.01.001.1 + Generate the 分部工程工程量汇总表 (3.3.3-01.01.01.000) + filled with all fields' data. """ - field = params['field_name'] proj = params.get('project_name') or data.get('project_name', '') - contractor = params.get('contractor') or data.get('contractor', '') - contract_section = params.get('contract_section') or data.get('contract_section', '') - supervision = params.get('supervision_company', '') + contractor = params.get('contractor', '') + contract_section = params.get('contract_section', '') + fields = data.get('fields', []) + + ws = wb.active + ws.title = '分部工程工程量汇总表' + + cw(ws, {1: 12, 2: 10, 3: 14, 4: 14, 5: 14, + 6: 8, 7: 8, 8: 8, 9: 8, 10: 8}) + rh(ws, {1: 36, 2: 24, 3: 24, 4: 30, 5: 24, + 6: 22, 7: 22, 8: 22, 9: 22, 10: 22, + 11: 22, 12: 22, 13: 22, 14: 22, 15: 22, + 16: 22, 17: 22, 18: 22, 19: 22, 20: 22, + 21: 22, 22: 22, 23: 22, 24: 24, 25: 24, 26: 24}) + + # Col A merges for data section (rows 6-21 or so) + n_fields = len(fields) + data_start = 6 # first data row + data_end = data_start + n_fields - 1 # last data row + total_row = data_end + 1 # 合计 row + sig_start = total_row + 1 # signature rows start + + # Row 1: Title + ms(ws, 1, 1, 1, 10, + '水浇地15~25°区域分部工程工程量汇总表', + font=TITLE_FONT, align=CA) + + # Row 2: 项目名称 + ms(ws, 2, 2, 1, 1, '项目名称', font=BOLD, align=CA) + ms(ws, 2, 2, 2, 10, proj, font=NORMAL, align=LA) + + # Row 3: 承包单位 + ms(ws, 3, 3, 1, 1, '承包单位名称', font=BOLD, align=CA) + ms(ws, 3, 3, 2, 8, contractor, font=NORMAL, align=LA) + ms(ws, 3, 3, 9, 10, f'合同段 {contract_section}', font=NORMAL, align=LA) + + # Row 4: Table header line 1 + ms(ws, 4, 5, 1, 1, '单元工程', font=HEADER_FONT, align=CA, border=THIN, fill=HDR_FILL) + ms(ws, 4, 5, 2, 2, '工 序 工 程 量', font=HEADER_FONT, align=CA, border=THIN, fill=HDR_FILL) + # Row 4 sub-headers + ms(ws, 4, 4, 3, 3, '工程量', font=HEADER_FONT, align=CA, border=THIN, fill=HDR_FILL) + ms(ws, 4, 4, 4, 4, '清理表土', font=HEADER_FONT, align=CA, border=THIN, fill=HDR_FILL) + ms(ws, 4, 4, 5, 5, '修平田地', font=HEADER_FONT, align=CA, border=THIN, fill=HDR_FILL) + ms(ws, 4, 4, 6, 6, '田埂修筑', font=HEADER_FONT, align=CA, border=THIN, fill=HDR_FILL) + # Fill remaining header cells + for c in range(7, 11): + ac(ws, 4, c, '', border=THIN, fill=HDR_FILL) + for c in range(3, 11): + ac(ws, 5, c, '', border=THIN, fill=HDR_FILL) + # Row 5 sub-header units + ac(ws, 5, 3, 'hm²', font=HEADER_FONT, align=CA, border=THIN, fill=HDR_FILL) + ac(ws, 5, 4, 'm³', font=HEADER_FONT, align=CA, border=THIN, fill=HDR_FILL) + ac(ws, 5, 5, 'm³', font=HEADER_FONT, align=CA, border=THIN, fill=HDR_FILL) + ac(ws, 5, 6, 'm³', font=HEADER_FONT, align=CA, border=THIN, fill=HDR_FILL) + + # Data rows + total_area = 0 + total_cl = 0 + total_xp = 0 + total_tg = 0 + + for i, f in enumerate(fields): + r = data_start + i + fd = f.get('field_display', f['name']) + ms(ws, r, r, 1, 1, fd, font=NORMAL, align=CA, border=THIN) + ms(ws, r, r, 2, 2, '', font=NORMAL, border=THIN) # empty col B + area = f.get('area', 0) + cl = f.get('清理表土', 0) + xp = f.get('修平田地', 0) + tg = f.get('田埂修筑', 0) + ac(ws, r, 3, area if area else '', font=NORMAL, align=CA, border=THIN, + nf='#,##0.0000' if area else None) + ac(ws, r, 4, cl if cl else '', font=NORMAL, align=CA, border=THIN, + nf='#,##0.00' if cl else None) + ac(ws, r, 5, xp if xp else '', font=NORMAL, align=CA, border=THIN, + nf='#,##0.00' if xp else None) + ac(ws, r, 6, tg if tg else '', font=NORMAL, align=CA, border=THIN, + nf='#,##0.00' if tg else None) + for c in range(7, 11): + ac(ws, r, c, '', font=NORMAL, border=THIN) + total_area += area + total_cl += cl + total_xp += xp + total_tg += tg + + # 合计 row + ms(ws, total_row, total_row, 1, 2, '合 计', font=BOLD, align=CA, border=THIN) + ac(ws, total_row, 3, total_area if total_area else '', font=BOLD, align=CA, + border=THIN, nf='#,##0.0000' if total_area else None) + ac(ws, total_row, 4, total_cl if total_cl else '', font=BOLD, align=CA, + border=THIN, nf='#,##0.00' if total_cl else None) + ac(ws, total_row, 5, total_xp if total_xp else '', font=BOLD, align=CA, + border=THIN, nf='#,##0.00' if total_xp else None) + ac(ws, total_row, 6, total_tg if total_tg else '', font=BOLD, align=CA, + border=THIN, nf='#,##0.00' if total_tg else None) + for c in range(7, 11): + ac(ws, total_row, c, '', font=BOLD, border=THIN) + + # Signature rows + ms(ws, sig_start, sig_start, 1, 3, + '承包单位(盖章)', font=NORMAL, align=LA) + ms(ws, sig_start, sig_start, 4, 7, + '监理机构(盖章)', font=NORMAL, align=LA) + ms(ws, sig_start, sig_start, 8, 10, + '项目承担单位(盖章)', font=NORMAL, align=LA) + + ms(ws, sig_start+1, sig_start+1, 1, 2, + '技术负责人:', font=NORMAL, align=LA) + ms(ws, sig_start+1, sig_start+1, 4, 5, + '监理工程师:', font=NORMAL, align=LA) + ms(ws, sig_start+1, sig_start+1, 8, 9, + '现场负责人:', font=NORMAL, align=LA) + + ms(ws, sig_start+2, sig_start+2, 1, 2, + '日 期:', font=NORMAL, align=LA) + ms(ws, sig_start+2, sig_start+2, 4, 5, + '日 期:', font=NORMAL, align=LA) + ms(ws, sig_start+2, sig_start+2, 8, 9, + '日 期:', font=NORMAL, align=LA) + + return fields # return for downstream use + + +# ══════════════════════════════════════════════════════════════════════ +# Output: 计量报验单 (per field) +# ══════════════════════════════════════════════════════════════════════ + +def generate_report(wb, data, params, field_info): + field_display = field_info.get('field_display', 'T3田块') + field_name = field_info.get('name', 'T3') + proj = params.get('project_name') or data.get('project_name', '') + contractor = params.get('contractor', '') + cs = params.get('contract_section', '') + supervision = params.get('supervision_company', '曲靖南天监理有限公司') ws = wb.active ws.title = '计量报验单' + cw(ws, {1: 16, 2: 16, 3: 16, 4: 14, 5: 14, 6: 12, 7: 12, 8: 10, 9: 10}) + rh(ws, {1: 36, 2: 24, 3: 24, 4: 30, 5: 24, 6: 24, 7: 24, 8: 24, + 9: 24, 10: 24, 11: 24, 12: 30, 13: 24, 14: 24, 15: 24}) - # Column widths (1-indexed) - set_col_widths(ws, {1: 16, 2: 16, 3: 16, 4: 14, 5: 14, 6: 12, 7: 12, 8: 10, 9: 10}) - set_row_heights(ws, {1: 36, 2: 24, 3: 24, 4: 30, 5: 24, 6: 24, 7: 24, 8: 24, - 9: 24, 10: 24, 11: 24, 12: 30, 13: 24, 14: 24, 15: 24}) + ms(ws, 1, 1, 1, 9, f'{field_display}单元工程计量报验单', font=TITLE_FONT, align=CA) + ms(ws, 2, 2, 1, 2, '项目名称', font=BOLD, align=CA) + ms(ws, 2, 2, 3, 7, proj, font=NORMAL, align=LA) + ms(ws, 2, 2, 8, 9, f'合同段 {cs}', font=NORMAL, align=LA) + ms(ws, 3, 3, 1, 1, '致:', font=BOLD, align=CA) + ms(ws, 3, 3, 2, 9, supervision, font=NORMAL, align=LA) + ms(ws, 4, 4, 1, 4, '我方按承包合同约定,已完成了', font=NORMAL, align=LA) + ms(ws, 4, 4, 5, 7, field_display, font=NORMAL, align=CA) + ms(ws, 4, 4, 8, 9, '单元工程(工序)的施工,其', font=NORMAL, align=LA) + ms(ws, 5, 5, 1, 9, '工程质量已经检查合格,并对工程量进行了计量测量,现提交计量结果,请予以核准。', font=NORMAL, align=LA) + ms(ws, 6, 6, 1, 9, '附件:', font=BOLD, align=LA) - # Row 1: Title - merge_and_set(ws, 1, 1, 1, 9, - f'{field}单元工程计量报验单', - font=Font(name='宋体', size=16, bold=True), - alignment=CENTER_ALIGN) - - # Row 2: 项目名称 & 合同段 - merge_and_set(ws, 2, 2, 1, 2, '项目名称', font=SIGN_FONT, alignment=CENTER_ALIGN) - merge_and_set(ws, 2, 2, 3, 7, proj, font=NORMAL_FONT, alignment=LEFT_ALIGN) - merge_and_set(ws, 2, 2, 8, 9, f'合同段 {contract_section}', font=NORMAL_FONT, alignment=LEFT_ALIGN) - - # Row 3: 致 监理单位 - merge_and_set(ws, 3, 3, 1, 1, '致:', font=SIGN_FONT, alignment=CENTER_ALIGN) - merge_and_set(ws, 3, 3, 2, 9, supervision, font=NORMAL_FONT, alignment=LEFT_ALIGN) - - # Row 4: 已完成...单元工程 - merge_and_set(ws, 4, 4, 1, 4, - '我方按承包合同约定,已完成了', - font=NORMAL_FONT, alignment=LEFT_ALIGN) - merge_and_set(ws, 4, 4, 5, 7, field, font=NORMAL_FONT, alignment=CENTER_ALIGN) - merge_and_set(ws, 4, 4, 8, 9, - '单元工程(工序)的施工,其', - font=NORMAL_FONT, alignment=LEFT_ALIGN) - - # Row 5: 工程质量... - merge_and_set(ws, 5, 5, 1, 9, - '工程质量已经检查合格,并对工程量进行了计量测量,现提交计量结果,请予以核准。', - font=NORMAL_FONT, alignment=LEFT_ALIGN) - - # Row 6: 附件: - merge_and_set(ws, 6, 6, 1, 9, '附件:', font=SIGN_FONT, alignment=LEFT_ALIGN) - - # Row 7-9: Attachment items - attachments = [ - ('1、工序工程计量统计表', '1'), - ('2、工程量测量资料', ''), - ('3、工序工程计量签证表', '3'), - ] - for i, (desc, pages) in enumerate(attachments): + attachs = [('1、工序工程计量统计表', '1'), ('2、工程量测量资料', ''), + ('3、工序工程计量签证表', '3')] + for i, (desc, pages) in enumerate(attachs): r = 7 + i - merge_and_set(ws, r, r, 1, 1, '', font=NORMAL_FONT) # spacing - merge_and_set(ws, r, r, 2, 6, desc, font=NORMAL_FONT, alignment=LEFT_ALIGN) + ms(ws, r, r, 1, 1, '', font=NORMAL) + ms(ws, r, r, 2, 6, desc, font=NORMAL, align=LA) if pages: - apply_cell(ws, r, 8, float(pages), font=NORMAL_FONT, alignment=CENTER_ALIGN) - apply_cell(ws, r, 9, '页', font=NORMAL_FONT, alignment=CENTER_ALIGN) + ac(ws, r, 8, float(pages), font=NORMAL, align=CA) + ac(ws, r, 9, '页', font=NORMAL, align=CA) - # Row 10: 承包单位 - merge_and_set(ws, 10, 10, 1, 3, - f'承包单位(盖章): {contractor}', - font=NORMAL_FONT, alignment=LEFT_ALIGN) - merge_and_set(ws, 10, 10, 4, 9, '', font=NORMAL_FONT) - - # Row 11: 项目经理 - merge_and_set(ws, 11, 11, 1, 3, - '项目经理(签字):', - font=NORMAL_FONT, alignment=LEFT_ALIGN) - merge_and_set(ws, 11, 11, 4, 9, '', font=NORMAL_FONT) - - # Row 12: 日期 - merge_and_set(ws, 12, 12, 1, 3, - '日 期:', - font=NORMAL_FONT, alignment=LEFT_ALIGN) - merge_and_set(ws, 12, 12, 4, 9, '', font=NORMAL_FONT) - - # Row 13: 审查意见 - merge_and_set(ws, 13, 13, 1, 5, - '监理机构审查意见:同意。', - font=NORMAL_FONT, alignment=LEFT_ALIGN) - merge_and_set(ws, 13, 13, 6, 9, - '项目承担单位审查意见:同意。', - font=NORMAL_FONT, alignment=LEFT_ALIGN) - - # Row 14: 签字 - merge_and_set(ws, 14, 14, 1, 3, - '监理工程师(签字):', - font=NORMAL_FONT, alignment=LEFT_ALIGN) - merge_and_set(ws, 14, 14, 6, 7, - '现场负责人(签字):', - font=NORMAL_FONT, alignment=LEFT_ALIGN) - - # Row 15: 日期 - merge_and_set(ws, 15, 15, 1, 3, - '日 期:', - font=NORMAL_FONT, alignment=LEFT_ALIGN) - merge_and_set(ws, 15, 15, 4, 5, '', font=NORMAL_FONT) - merge_and_set(ws, 15, 15, 6, 7, - '日 期:', - font=NORMAL_FONT, alignment=LEFT_ALIGN) - - apply_cell(ws, 14, 8, '', font=NORMAL_FONT) - apply_cell(ws, 14, 9, '', font=NORMAL_FONT) - apply_cell(ws, 15, 8, '', font=NORMAL_FONT) - apply_cell(ws, 15, 9, '', font=NORMAL_FONT) + ms(ws, 10, 10, 1, 3, f'承包单位(盖章): {contractor}', font=NORMAL, align=LA) + ms(ws, 10, 10, 4, 9, '', font=NORMAL) + ms(ws, 11, 11, 1, 3, '项目经理(签字):', font=NORMAL, align=LA) + ms(ws, 11, 11, 4, 9, '', font=NORMAL) + ms(ws, 12, 12, 1, 3, '日 期:', font=NORMAL, align=LA) + ms(ws, 12, 12, 4, 9, '', font=NORMAL) + ms(ws, 13, 13, 1, 5, '监理机构审查意见:同意。', font=NORMAL, align=LA) + ms(ws, 13, 13, 6, 9, '项目承担单位审查意见:同意。', font=NORMAL, align=LA) + ms(ws, 14, 14, 1, 3, '监理工程师(签字):', font=NORMAL, align=LA) + ms(ws, 14, 14, 6, 7, '现场负责人(签字):', font=NORMAL, align=LA) + ms(ws, 15, 15, 1, 3, '日 期:', font=NORMAL, align=LA) + ms(ws, 15, 15, 6, 7, '日 期:', font=NORMAL, align=LA) -def generate_statistics_table(wb, data, params): - """ - 输出文件2:工序工程量统计表 - 文件名: 02_{field_name}单元工程工序工程量统计表.xlsx - Template: 3.3.3-01.01.01.001.2 - """ - field = params['field_name'] +# ══════════════════════════════════════════════════════════════════════ +# Output: 工序工程量统计表 (per field) +# ══════════════════════════════════════════════════════════════════════ + +def generate_statistics(wb, data, params, field_info): + field_display = field_info.get('field_display', 'T3田块') proj = params.get('project_name') or data.get('project_name', '') - contractor = params.get('contractor') or data.get('contractor', '') - contract_section = params.get('contract_section') or data.get('contract_section', '') - qty = data['quantities'] + contractor = params.get('contractor', '') + cs = params.get('contract_section', '') + qty = field_info ws = wb.active ws.title = '工序工程量统计表' + cw(ws, {1: 8, 2: 16, 3: 10, 4: 14, 5: 14, 6: 14, + 7: 8, 8: 8, 9: 8, 10: 8, 11: 8, 12: 8, 13: 8, 14: 8, 15: 8}) + rh(ws, {1: 36, 2: 24, 3: 24, 4: 30, 5: 24, 6: 24, 7: 24, 8: 24, 9: 24, 10: 24, 11: 24}) - set_col_widths(ws, {1: 8, 2: 16, 3: 10, 4: 14, 5: 14, 6: 14, - 7: 8, 8: 8, 9: 8, 10: 8, 11: 8, 12: 8, 13: 8, 14: 8, 15: 8}) - set_row_heights(ws, {1: 36, 2: 24, 3: 24, 4: 30, 5: 24, 6: 24, 7: 24, - 8: 24, 9: 24, 10: 24, 11: 24}) + ms(ws, 1, 1, 1, 15, f'{field_display}单元工程工序工程量统计表', font=TITLE_FONT, align=CA) + ms(ws, 2, 2, 1, 2, '项目名称', font=BOLD, align=CA) + ms(ws, 2, 2, 3, 12, proj, font=NORMAL, align=LA) + ms(ws, 2, 2, 14, 15, f'合同段 {cs}', font=NORMAL, align=LA) + ac(ws, 2, 13, '', font=NORMAL) - # Row 1: Title - merge_and_set(ws, 1, 1, 1, 15, - f'{field}单元工程工序工程量统计表', - font=Font(name='宋体', size=16, bold=True), - alignment=CENTER_ALIGN) + ms(ws, 3, 3, 1, 2, '承包单位', font=BOLD, align=CA) + ms(ws, 3, 3, 3, 15, contractor, font=NORMAL, align=LA) - # Row 2: 项目名称 - merge_and_set(ws, 2, 2, 1, 2, '项目名称', font=SIGN_FONT, alignment=CENTER_ALIGN) - merge_and_set(ws, 2, 2, 3, 12, proj, font=NORMAL_FONT, alignment=LEFT_ALIGN) - merge_and_set(ws, 2, 2, 14, 15, f'合同段 {contract_section}', - font=NORMAL_FONT, alignment=LEFT_ALIGN) - apply_cell(ws, 2, 13, '', font=NORMAL_FONT) - - # Row 3: 承包单位 - merge_and_set(ws, 3, 3, 1, 2, '承包单位', font=SIGN_FONT, alignment=CENTER_ALIGN) - merge_and_set(ws, 3, 3, 3, 15, contractor, font=NORMAL_FONT, alignment=LEFT_ALIGN) - - # Row 4: Table header row 1 - merge_and_set(ws, 4, 5, 1, 1, '序号', font=HEADER_FONT, alignment=CENTER_ALIGN, - border=THIN_BORDER, fill=HEADER_FILL) - merge_and_set(ws, 4, 5, 2, 2, '工程验收段名称及部位', font=HEADER_FONT, - alignment=CENTER_ALIGN, border=THIN_BORDER, fill=HEADER_FILL) - merge_and_set(ws, 4, 4, 3, 3, '工程量', font=HEADER_FONT, - alignment=CENTER_ALIGN, border=THIN_BORDER, fill=HEADER_FILL) - merge_and_set(ws, 4, 4, 4, 6, '工 序 工 程 量', font=HEADER_FONT, - alignment=CENTER_ALIGN, border=THIN_BORDER, fill=HEADER_FILL) - # fill remaining header cells + # Header rows + ms(ws, 4, 5, 1, 1, '序号', font=HEADER_FONT, align=CA, border=THIN, fill=HDR_FILL) + ms(ws, 4, 5, 2, 2, '工程验收段名称及部位', font=HEADER_FONT, align=CA, border=THIN, fill=HDR_FILL) + ms(ws, 4, 4, 3, 3, '工程量', font=HEADER_FONT, align=CA, border=THIN, fill=HDR_FILL) + ms(ws, 4, 4, 4, 6, '工 序 工 程 量', font=HEADER_FONT, align=CA, border=THIN, fill=HDR_FILL) for c in range(7, 16): - ws.cell(row=4, column=c).border = THIN_BORDER - ws.cell(row=4, column=c).fill = HEADER_FILL + ac(ws, 4, c, '', border=THIN, fill=HDR_FILL) + ac(ws, 5, c, '', border=THIN, fill=HDR_FILL) + ac(ws, 5, 3, '', font=HEADER_FONT, align=CA, border=THIN, fill=HDR_FILL) + for c, lbl in [(4, '清理表土'), (5, '修平田地'), (6, '田埂修筑')]: + ac(ws, 5, c, lbl, font=HEADER_FONT, align=CA, border=THIN, fill=HDR_FILL) + + # Data row + ac(ws, 6, 1, 1, font=NORMAL, align=CA, border=THIN) + ac(ws, 6, 2, field_display, font=NORMAL, align=CA, border=THIN) + ac(ws, 6, 3, '', font=NORMAL, align=CA, border=THIN) + for c, pn in [(4, '清理表土'), (5, '修平田地'), (6, '田埂修筑')]: + val = qty.get(pn, 0) + ac(ws, 6, c, val if val else '', font=NORMAL, align=CA, border=THIN, + nf='#,##0.00' if val else None) for c in range(7, 16): - ws.cell(row=5, column=c).border = THIN_BORDER - ws.cell(row=5, column=c).fill = HEADER_FILL + ac(ws, 6, c, '', font=NORMAL, align=CA, border=THIN) - # Row 5: Sub-header for 清理表土, 修平田地, 田埂修筑 - apply_cell(ws, 5, 3, '', font=HEADER_FONT, alignment=CENTER_ALIGN, - border=THIN_BORDER, fill=HEADER_FILL) - sub_headers = {4: '清理表土', 5: '修平田地', 6: '田埂修筑'} - for c, text in sub_headers.items(): - apply_cell(ws, 5, c, text, font=HEADER_FONT, alignment=CENTER_ALIGN, - border=THIN_BORDER, fill=HEADER_FILL) - - # Row 6: Data - hm2 = '' - apply_cell(ws, 6, 1, 1, font=NORMAL_FONT, alignment=CENTER_ALIGN, border=THIN_BORDER) - apply_cell(ws, 6, 2, field, font=NORMAL_FONT, alignment=CENTER_ALIGN, border=THIN_BORDER) - apply_cell(ws, 6, 3, hm2, font=NORMAL_FONT, alignment=CENTER_ALIGN, border=THIN_BORDER) - for c_idx, pname in [(4, '清理表土'), (5, '修平田地'), (6, '田埂修筑')]: - val = qty.get(pname, 0) - apply_cell(ws, 6, c_idx, val if val else '', - font=NORMAL_FONT, alignment=CENTER_ALIGN, border=THIN_BORDER, - number_format='#,##0.00' if val else None) + # 合计 row + ms(ws, 7, 7, 1, 2, '合 计', font=BOLD, align=CA, border=THIN) + ac(ws, 7, 3, '', font=BOLD, align=CA, border=THIN) + for c, pn in [(4, '清理表土'), (5, '修平田地'), (6, '田埂修筑')]: + val = qty.get(pn, 0) + ac(ws, 7, c, val if val else '', font=BOLD, align=CA, border=THIN, + nf='#,##0.00' if val else None) for c in range(7, 16): - apply_cell(ws, 6, c, '', font=NORMAL_FONT, alignment=CENTER_ALIGN, border=THIN_BORDER) + ac(ws, 7, c, '', font=BOLD, align=CA, border=THIN) - # Row 7: 合计 - merge_and_set(ws, 7, 7, 1, 2, '合 计', font=SIGN_FONT, alignment=CENTER_ALIGN, - border=THIN_BORDER) - apply_cell(ws, 7, 3, '', font=SIGN_FONT, alignment=CENTER_ALIGN, border=THIN_BORDER) - for c_idx, pname in [(4, '清理表土'), (5, '修平田地'), (6, '田埂修筑')]: - val = qty.get(pname, 0) - apply_cell(ws, 7, c_idx, val if val else '', - font=SIGN_FONT, alignment=CENTER_ALIGN, border=THIN_BORDER, - number_format='#,##0.00' if val else None) - for c in range(7, 16): - apply_cell(ws, 7, c, '', font=SIGN_FONT, alignment=CENTER_ALIGN, border=THIN_BORDER) - - # Row 8-11: Signature area - sig_labels = [ - ('承包单位(盖章):', '监理机构(盖章):', '项目承担单位(盖章):'), - ('技术负责人:', '监理工程师:', '现场负责人:'), - ('日 期:', '日 期:', '日 期:'), - ] - block_cols = [(1, 5), (6, 10), (11, 15)] - for ri, (l1, l2, l3) in enumerate(sig_labels): + # Signature + sigs = [('承包单位(盖章):', '监理机构(盖章):', '项目承担单位(盖章):'), + ('技术负责人:', '监理工程师:', '现场负责人:'), + ('日 期:', '日 期:', '日 期:')] + for ri, (l1, l2, l3) in enumerate(sigs): r = 8 + ri - merge_and_set(ws, r, r, 1, 5, l1, font=NORMAL_FONT, alignment=LEFT_ALIGN) - merge_and_set(ws, r, r, 6, 10, l2, font=NORMAL_FONT, alignment=LEFT_ALIGN) - merge_and_set(ws, r, r, 11, 15, l3, font=NORMAL_FONT, alignment=LEFT_ALIGN) + ms(ws, r, r, 1, 5, l1, font=NORMAL, align=LA) + ms(ws, r, r, 6, 10, l2, font=NORMAL, align=LA) + ms(ws, r, r, 11, 15, l3, font=NORMAL, align=LA) -def generate_certificate(wb, data, params, process_name, quantity, date_val=None): - """ - 输出文件3.x:工序工程量签证 - Template: 3.3.3-01.01.01.001.3.01.xx - """ - field = params['field_name'] +# ══════════════════════════════════════════════════════════════════════ +# Output: 工序工程量签证 (per process) +# ══════════════════════════════════════════════════════════════════════ + +def generate_certificate(wb, data, params, field_info, process_name): + field_display = field_info.get('field_display', 'T3田块') proj = params.get('project_name') or data.get('project_name', '') - contractor = params.get('contractor') or data.get('contractor', '') - contract_section = params.get('contract_section') or data.get('contract_section', '') - supervision = params.get('supervision_company', '') - project_owner = params.get('project_owner', '') + contractor = params.get('contractor', '') + cs = params.get('contract_section', '') + supervision = params.get('supervision_company', '曲靖南天监理有限公司') + owner = params.get('project_owner', '巧家县国土资源局') sub_project = params.get('sub_project_name', '水浇地15~25°区域') unit_eng = params.get('unit_engineer_name', '田块修筑') + quantity = field_info.get(process_name, 0) ws = wb.active ws.title = '工程量签证' + cw(ws, {1: 16, 2: 12, 3: 14, 4: 14, 5: 14, + 6: 12, 7: 12, 8: 12, 9: 12, 10: 10, 11: 10, 12: 10}) + rh(ws, {1: 36, 2: 24, 3: 24, 4: 24, 5: 24, 6: 24, + 7: 30, 8: 30, 9: 24, 10: 24, 11: 24, 12: 24, + 13: 24, 14: 24, 15: 36, 16: 36, 17: 30, 18: 24, + 19: 24, 20: 24, 21: 24, 22: 24}) - set_col_widths(ws, {1: 16, 2: 12, 3: 14, 4: 14, 5: 14, - 6: 12, 7: 12, 8: 12, 9: 12, 10: 10, 11: 10, 12: 10}) - set_row_heights(ws, {1: 36, 2: 24, 3: 24, 4: 24, 5: 24, 6: 24, - 7: 30, 8: 30, 9: 24, 10: 24, 11: 24, 12: 24, - 13: 24, 14: 24, 15: 36, 16: 36, 17: 30, 18: 24, - 19: 24, 20: 24, 21: 24, 22: 24}) + ms(ws, 1, 1, 1, 12, '工序(验收段)工程量签证', font=TITLE_FONT, align=CA) + ms(ws, 2, 2, 1, 2, '项目名称', font=BOLD, align=CA) + ms(ws, 2, 2, 3, 8, proj, font=NORMAL, align=LA) + ms(ws, 2, 2, 10, 12, f'合同段 {cs}', font=NORMAL, align=LA) + ac(ws, 2, 9, '', font=NORMAL) - # Row 1: Title - merge_and_set(ws, 1, 1, 1, 12, - '工序(验收段)工程量签证', - font=Font(name='宋体', size=16, bold=True), - alignment=CENTER_ALIGN) + ms(ws, 3, 3, 1, 2, '单项工程名称', font=BOLD, align=CA) + ms(ws, 3, 3, 3, 5, '土地平整工程', font=NORMAL, align=CA) + ms(ws, 3, 3, 6, 8, '分部工程名称', font=BOLD, align=CA) + ms(ws, 3, 3, 9, 12, sub_project, font=NORMAL, align=CA) - # Row 2: 项目名称 / 合同段 - merge_and_set(ws, 2, 2, 1, 2, '项目名称', font=SIGN_FONT, alignment=CENTER_ALIGN) - merge_and_set(ws, 2, 2, 3, 8, proj, font=NORMAL_FONT, alignment=LEFT_ALIGN) - merge_and_set(ws, 2, 2, 10, 12, f'合同段 {contract_section}', - font=NORMAL_FONT, alignment=LEFT_ALIGN) - apply_cell(ws, 2, 9, '', font=NORMAL_FONT) + ms(ws, 4, 4, 1, 2, '单位工程名称', font=BOLD, align=CA) + ms(ws, 4, 4, 3, 5, unit_eng, font=NORMAL, align=CA) + ms(ws, 4, 4, 6, 8, '单元工程名称', font=BOLD, align=CA) + ms(ws, 4, 4, 9, 12, field_display, font=NORMAL, align=CA) - # Row 3: 单项/分部/单元/工程名称 - merge_and_set(ws, 3, 3, 1, 2, '单项工程名称', font=SIGN_FONT, alignment=CENTER_ALIGN) - merge_and_set(ws, 3, 3, 3, 5, '土地平整工程', font=NORMAL_FONT, alignment=CENTER_ALIGN) - merge_and_set(ws, 3, 3, 6, 8, '分部工程名称', font=SIGN_FONT, alignment=CENTER_ALIGN) - merge_and_set(ws, 3, 3, 9, 12, sub_project, font=NORMAL_FONT, alignment=CENTER_ALIGN) + ms(ws, 5, 5, 1, 1, '致:', font=BOLD, align=LA) + ms(ws, 5, 5, 2, 12, owner, font=NORMAL, align=LA) + ms(ws, 6, 6, 1, 1, '', font=NORMAL) + ms(ws, 6, 6, 2, 12, supervision, font=NORMAL, align=LA) - # Row 4: 单位/单元工程 - merge_and_set(ws, 4, 4, 1, 2, '单位工程名称', font=SIGN_FONT, alignment=CENTER_ALIGN) - merge_and_set(ws, 4, 4, 3, 5, unit_eng, font=NORMAL_FONT, alignment=CENTER_ALIGN) - merge_and_set(ws, 4, 4, 6, 8, '单元工程名称', font=SIGN_FONT, alignment=CENTER_ALIGN) - merge_and_set(ws, 4, 4, 9, 12, field, font=NORMAL_FONT, alignment=CENTER_ALIGN) + ms(ws, 7, 7, 1, 4, '我方按设计要求完成', font=NORMAL, align=LA) + ms(ws, 7, 7, 5, 9, process_name, font=NORMAL, align=CA) + ms(ws, 7, 7, 10, 12, '工序验收段施工,', font=NORMAL, align=LA) + ms(ws, 8, 8, 1, 12, '经工序质量评定合格,请予以对其工程量进行核定。', font=NORMAL, align=LA) - # Row 5-6: 致 业主/监理 - merge_and_set(ws, 5, 5, 1, 1, '致:', font=SIGN_FONT, alignment=LEFT_ALIGN) - merge_and_set(ws, 5, 5, 2, 12, project_owner, font=NORMAL_FONT, alignment=LEFT_ALIGN) - merge_and_set(ws, 6, 6, 1, 1, '', font=NORMAL_FONT) - merge_and_set(ws, 6, 6, 2, 12, supervision, font=NORMAL_FONT, alignment=LEFT_ALIGN) + ms(ws, 9, 9, 1, 3, '承包单位(盖章):', font=BOLD, align=LA) + ms(ws, 9, 9, 4, 12, contractor, font=NORMAL, align=LA) + ms(ws, 10, 10, 1, 3, '项目经理(签字):', font=NORMAL, align=LA) + ms(ws, 10, 10, 4, 12, '', font=NORMAL) + ms(ws, 11, 11, 1, 3, '日 期:', font=NORMAL, align=LA) + ms(ws, 11, 11, 4, 12, '', font=NORMAL) - # Row 7: 我方按设计要求完成... - merge_and_set(ws, 7, 7, 1, 4, - '我方按设计要求完成', - font=NORMAL_FONT, alignment=LEFT_ALIGN) - merge_and_set(ws, 7, 7, 5, 9, process_name, font=NORMAL_FONT, alignment=CENTER_ALIGN) - merge_and_set(ws, 7, 7, 10, 12, - '工序验收段施工,', - font=NORMAL_FONT, alignment=LEFT_ALIGN) + ms(ws, 12, 12, 1, 12, '签证内容及图示:', font=BOLD, align=LA) + ms(ws, 13, 13, 1, 4, f'1、{field_display}', font=NORMAL, align=LA) + ms(ws, 13, 13, 5, 12, '验收段的工序工程量', font=NORMAL, align=LA) + ms(ws, 14, 14, 1, 12, '2、图示详见施工图册', font=NORMAL, align=LA) + ms(ws, 15, 15, 1, 12, '', font=NORMAL) + ms(ws, 16, 16, 1, 12, '', font=NORMAL) - # Row 8: 经工序... - merge_and_set(ws, 8, 8, 1, 12, - '经工序质量评定合格,请予以对其工程量进行核定。', - font=NORMAL_FONT, alignment=LEFT_ALIGN) + ms(ws, 17, 17, 1, 12, '工程量计算:', font=BOLD, align=LA) + qty_str = f'{quantity:.2f} m³' if quantity else '0.00 m³' + ms(ws, 18, 18, 1, 4, f'1、{process_name}', font=BOLD, align=LA) + ms(ws, 18, 18, 5, 12, qty_str, font=NORMAL, align=LA) + ms(ws, 19, 19, 1, 4, '2、工程量计算表达式', font=NORMAL, align=LA) + ms(ws, 19, 19, 5, 12, '', font=NORMAL) - # Row 9: 承包单位 - merge_and_set(ws, 9, 9, 1, 3, '承包单位(盖章):', font=SIGN_FONT, alignment=LEFT_ALIGN) - merge_and_set(ws, 9, 9, 4, 12, contractor, font=NORMAL_FONT, alignment=LEFT_ALIGN) - - # Row 10: 项目经理 - merge_and_set(ws, 10, 10, 1, 3, '项目经理(签字):', font=NORMAL_FONT, alignment=LEFT_ALIGN) - merge_and_set(ws, 10, 10, 4, 6, '', font=NORMAL_FONT) - merge_and_set(ws, 10, 10, 7, 12, '', font=NORMAL_FONT) - - # Row 11: 日期 - merge_and_set(ws, 11, 11, 1, 3, '日 期:', font=NORMAL_FONT, alignment=LEFT_ALIGN) - merge_and_set(ws, 11, 11, 4, 12, '', font=NORMAL_FONT) - - # Row 12: 签证内容及图示 - merge_and_set(ws, 12, 12, 1, 12, - '签证内容及图示:', - font=SIGN_FONT, alignment=LEFT_ALIGN) - - # Row 13: 1、田块 - merge_and_set(ws, 13, 13, 1, 4, f'1、{field}', font=NORMAL_FONT, alignment=LEFT_ALIGN) - merge_and_set(ws, 13, 13, 5, 12, - '验收段的工序工程量', - font=NORMAL_FONT, alignment=LEFT_ALIGN) - - # Row 14: 2、图示 - merge_and_set(ws, 14, 14, 1, 12, - '2、图示详见施工图册', - font=NORMAL_FONT, alignment=LEFT_ALIGN) - - # Row 15-16: blank spacing for diagram - merge_and_set(ws, 15, 15, 1, 12, '', font=NORMAL_FONT) - merge_and_set(ws, 16, 16, 1, 12, '', font=NORMAL_FONT) - - # Row 17: 工程量计算 - merge_and_set(ws, 17, 17, 1, 12, - '工程量计算:', - font=SIGN_FONT, alignment=LEFT_ALIGN) - - # Row 18: 1、工序名称 + 数量 - quantity_str = f'{quantity:.2f} m³' if quantity else '0.00 m³' - merge_and_set(ws, 18, 18, 1, 4, f'1、{process_name}', font=SIGN_FONT, alignment=LEFT_ALIGN) - merge_and_set(ws, 18, 18, 5, 12, quantity_str, font=NORMAL_FONT, alignment=LEFT_ALIGN) - - # Row 19: 2、表达式 - merge_and_set(ws, 19, 19, 1, 4, '2、工程量计算表达式', font=NORMAL_FONT, alignment=LEFT_ALIGN) - merge_and_set(ws, 19, 19, 5, 12, '', font=NORMAL_FONT) - - # Row 20: Signatures row 1 - merge_and_set(ws, 20, 20, 1, 4, '承包单位(盖章):', font=NORMAL_FONT, alignment=LEFT_ALIGN) - merge_and_set(ws, 20, 20, 5, 8, '监理机构(盖章):', font=NORMAL_FONT, alignment=LEFT_ALIGN) - merge_and_set(ws, 20, 20, 9, 12, '项目承担单位(盖章):', - font=NORMAL_FONT, alignment=LEFT_ALIGN) - - # Row 21: Signatures row 2 - merge_and_set(ws, 21, 21, 1, 2, '技术负责人:', font=NORMAL_FONT, alignment=LEFT_ALIGN) - merge_and_set(ws, 21, 21, 5, 6, '监理工程师:', font=NORMAL_FONT, alignment=LEFT_ALIGN) - merge_and_set(ws, 21, 21, 9, 10, '现场负责人:', font=NORMAL_FONT, alignment=LEFT_ALIGN) - - # Row 22: Signatures row 3 (dates) - merge_and_set(ws, 22, 22, 1, 2, '日 期:', font=NORMAL_FONT, alignment=LEFT_ALIGN) - merge_and_set(ws, 22, 22, 3, 4, '', font=NORMAL_FONT) - merge_and_set(ws, 22, 22, 5, 6, '日 期:', font=NORMAL_FONT, alignment=LEFT_ALIGN) - merge_and_set(ws, 22, 22, 7, 8, '', font=NORMAL_FONT) - merge_and_set(ws, 22, 22, 9, 10, '日 期:', font=NORMAL_FONT, alignment=LEFT_ALIGN) - merge_and_set(ws, 22, 22, 11, 12, '', font=NORMAL_FONT) - - # Apply full borders to all rows (for visual consistency) - for r in range(1, 23): - for c in range(1, 13): - cell = ws.cell(row=r, column=c) - if cell.border == Border(): - cell.border = THIN_BORDER + ms(ws, 20, 20, 1, 4, '承包单位(盖章):', font=NORMAL, align=LA) + ms(ws, 20, 20, 5, 8, '监理机构(盖章):', font=NORMAL, align=LA) + ms(ws, 20, 20, 9, 12, '项目承担单位(盖章):', font=NORMAL, align=LA) + ms(ws, 21, 21, 1, 2, '技术负责人:', font=NORMAL, align=LA) + ms(ws, 21, 21, 5, 6, '监理工程师:', font=NORMAL, align=LA) + ms(ws, 21, 21, 9, 10, '现场负责人:', font=NORMAL, align=LA) + ms(ws, 22, 22, 1, 2, '日 期:', font=NORMAL, align=LA) + ms(ws, 22, 22, 5, 6, '日 期:', font=NORMAL, align=LA) + ms(ws, 22, 22, 9, 10, '日 期:', font=NORMAL, align=LA) # ══════════════════════════════════════════════════════════════════════ @@ -549,130 +551,119 @@ def generate_certificate(wb, data, params, process_name, quantity, date_val=None def main(): if len(sys.argv) > 1: - params_raw = sys.argv[1] - try: - p = json.loads(params_raw) - except json.JSONDecodeError: - print(json.dumps({"error": f"无法解析参数 JSON: {params_raw}"})) - sys.exit(1) + p = json.loads(sys.argv[1]) elif 'PARAMS_FILE' in os.environ: - with open(os.environ['PARAMS_FILE'], 'r') as f: + with open(os.environ['PARAMS_FILE']) as f: p = json.load(f) else: p = {} - # For development: use env vars as fallback - for key in ('input_path', 'output_dir', 'field_name', 'sub_project_name', - 'unit_engineer_name', 'project_name', 'contractor', - 'contract_section', 'supervision_company', 'project_owner'): + for key in ('input_table_path', 'output_dir', 'project_name', + 'contractor', 'contract_section', 'supervision_company', + 'project_owner', 'sub_project_name', 'unit_engineer_name', + 'generate_all_fields'): if key.upper() in os.environ: p[key] = os.environ[key.upper()] - required = ['input_path', 'output_dir'] + required = ['input_table_path', 'output_dir'] missing = [k for k in required if k not in p or not p[k]] if missing: print(json.dumps({ "error": f"缺少必要参数: {', '.join(missing)}", - "usage": "python generate.py '{\"input_path\": \"...\", \"output_dir\": \"...\"}'" })) sys.exit(1) - input_path = p['input_path'] + input_path = p['input_table_path'] output_dir = p['output_dir'] os.makedirs(output_dir, exist_ok=True) - # ── 1. Read input ────────────────────────────────────────────── - print(json.dumps({"step": "read_input", "status": "start", "path": input_path})) + # ── 1. Parse input ───────────────────────────────────────────── + print(json.dumps({"step": "parse_input", "status": "start", "path": input_path})) try: - data = read_input(input_path) + data = parse_input(input_path) except Exception as e: - print(json.dumps({"error": f"读取结算表失败: {str(e)}"})) + print(json.dumps({"error": f"解析输入表失败: {str(e)}"})) sys.exit(1) + fields = data.get('fields', []) print(json.dumps({ - "step": "read_input", + "step": "parse_input", "status": "ok", - "project_name": data['project_name'], - "contractor": data['contractor'], - "quantities": data['quantities'], + "project": data.get('project_name', ''), + "field_count": len(fields), + "fields": [f['name'] for f in fields], })) - qty = data['quantities'] - - # ── 2. Collect params with fallback ───────────────────────────── + # ── 2. Resolve params ────────────────────────────────────────── params = { - 'field_name': p.get('field_name', 'T3田块'), + 'project_name': p.get('project_name') or data.get('project_name', ''), + 'contractor': p.get('contractor', ''), + 'contract_section': p.get('contract_section', ''), 'sub_project_name': p.get('sub_project_name', '水浇地15~25°区域'), 'unit_engineer_name': p.get('unit_engineer_name', '田块修筑'), - 'project_name': p.get('project_name') or data.get('project_name', ''), - 'contractor': p.get('contractor') or data.get('contractor', ''), - 'contract_section': p.get('contract_section') or data.get('contract_section', ''), 'supervision_company': p.get('supervision_company', '曲靖南天监理有限公司'), 'project_owner': p.get('project_owner', '巧家县国土资源局'), } - # ── 3. Generate output documents ──────────────────────────────── - generated = [] + generate_all = p.get('generate_all_fields', 'true').lower() in ('true', '1', 'yes') - # 3.1 计量报验单 - wb1 = openpyxl.Workbook() - generate_report_form(wb1, data, params) - f1 = os.path.join(output_dir, f'01_{params["field_name"]}单元工程计量报验单.xlsx') - wb1.save(f1) - generated.append(f1) - print(json.dumps({"step": "generate", "file": f1, "status": "ok"})) + # ── 3. Generate 分部工程工程量汇总表 ───────────────────────────── + wb0 = openpyxl.Workbook() + generate_subitem_summary(wb0, data, params) + f0 = os.path.join(output_dir, '01_水浇地15~25°区域分部工程工程量汇总表.xlsx') + wb0.save(f0) + print(json.dumps({"step": "generate", "file": f0, "status": "ok"})) + generated = [f0] - # 3.2 工序工程量统计表 - wb2 = openpyxl.Workbook() - generate_statistics_table(wb2, data, params) - f2 = os.path.join(output_dir, f'02_{params["field_name"]}单元工程工序工程量统计表.xlsx') - wb2.save(f2) - generated.append(f2) - print(json.dumps({"step": "generate", "file": f2, "status": "ok"})) + # ── 4. Generate per-field documents ───────────────────────────── + target_fields = fields if generate_all else [fields[0]] if fields else [] - # 3.3 清理表土签证 - proc_name = '清理表土' - q_val = qty.get(proc_name, 0) - wb31 = openpyxl.Workbook() - generate_certificate(wb31, data, params, proc_name, q_val) - f31 = os.path.join(output_dir, f'03.01_{proc_name}工序工程量签证.xlsx') - wb31.save(f31) - generated.append(f31) - print(json.dumps({"step": "generate", "file": f31, "status": "ok"})) + for field_info in target_fields: + fd = field_info.get('field_display', field_info['name']) + fn = field_info.get('name', fd) + prefix = f'02_{fn}' - # 3.4 修平田地签证 - proc_name = '修平田地' - q_val = qty.get(proc_name, 0) - wb32 = openpyxl.Workbook() - generate_certificate(wb32, data, params, proc_name, q_val) - f32 = os.path.join(output_dir, f'03.02_{proc_name}工序工程量签证.xlsx') - wb32.save(f32) - generated.append(f32) - print(json.dumps({"step": "generate", "file": f32, "status": "ok"})) + # 报验单 + wb1 = openpyxl.Workbook() + generate_report(wb1, data, params, field_info) + f1 = os.path.join(output_dir, f'{prefix}_{fd}单元工程计量报验单.xlsx') + wb1.save(f1) + generated.append(f1) + print(json.dumps({"step": "generate", "file": f1, "status": "ok"})) - # 3.5 田埂修筑签证 - proc_name = '田埂修筑' - q_val = qty.get(proc_name, 0) - wb33 = openpyxl.Workbook() - generate_certificate(wb33, data, params, proc_name, q_val) - f33 = os.path.join(output_dir, f'03.03_{proc_name}工序工程量签证.xlsx') - wb33.save(f33) - generated.append(f33) - print(json.dumps({"step": "generate", "file": f33, "status": "ok"})) + # 统计表 + wb2 = openpyxl.Workbook() + generate_statistics(wb2, data, params, field_info) + f2 = os.path.join(output_dir, f'{prefix}_{fd}单元工程工序工程量统计表.xlsx') + wb2.save(f2) + generated.append(f2) + print(json.dumps({"step": "generate", "file": f2, "status": "ok"})) + + # 3x签证 + for proc in ['清理表土', '修平田地', '田埂修筑']: + wb3 = openpyxl.Workbook() + generate_certificate(wb3, data, params, field_info, proc) + f3 = os.path.join(output_dir, f'{prefix}_{proc}工序工程量签证.xlsx') + wb3.save(f3) + generated.append(f3) + print(json.dumps({"step": "generate", "file": f3, "status": "ok"})) + + # ── Summary ────────────────────────────────────────────────────── + total_summary = { + "清理表土": round(sum(f.get('清理表土', 0) for f in fields), 2), + "修平田地": round(sum(f.get('修平田地', 0) for f in fields), 2), + "田埂修筑": round(sum(f.get('田埂修筑', 0) for f in fields), 2), + } - # ── Done ──────────────────────────────────────────────────────── result = { "status": "success", "output_dir": output_dir, "files": generated, "summary": { - "field": params['field_name'], "project": params['project_name'], "contractor": params['contractor'], - "quantities": { - "清理表土": round(qty.get('清理表土', 0), 2), - "修平田地": round(qty.get('修平田地', 0), 2), - "田埂修筑": round(qty.get('田埂修筑', 0), 2), - } + "total_fields": len(fields), + "generated_fields": len(target_fields), + "total_quantities": total_summary, } } print(json.dumps(result)) diff --git a/test_input_filled.xlsx b/test_input_filled.xlsx new file mode 100644 index 0000000..eab2a35 Binary files /dev/null and b/test_input_filled.xlsx differ diff --git a/test_output/01_T3田块单元工程计量报验单.xlsx b/test_output/01_T3田块单元工程计量报验单.xlsx new file mode 100644 index 0000000..375cca9 Binary files /dev/null and b/test_output/01_T3田块单元工程计量报验单.xlsx differ diff --git a/test_output/02_T3田块单元工程工序工程量统计表.xlsx b/test_output/02_T3田块单元工程工序工程量统计表.xlsx new file mode 100644 index 0000000..cd6e7c4 Binary files /dev/null and b/test_output/02_T3田块单元工程工序工程量统计表.xlsx differ diff --git a/test_output/03.01_清理表土工序工程量签证.xlsx b/test_output/03.01_清理表土工序工程量签证.xlsx new file mode 100644 index 0000000..ef40e14 Binary files /dev/null and b/test_output/03.01_清理表土工序工程量签证.xlsx differ diff --git a/test_output/03.02_修平田地工序工程量签证.xlsx b/test_output/03.02_修平田地工序工程量签证.xlsx new file mode 100644 index 0000000..f5d548e Binary files /dev/null and b/test_output/03.02_修平田地工序工程量签证.xlsx differ diff --git a/test_output/03.03_田埂修筑工序工程量签证.xlsx b/test_output/03.03_田埂修筑工序工程量签证.xlsx new file mode 100644 index 0000000..3ec8c82 Binary files /dev/null and b/test_output/03.03_田埂修筑工序工程量签证.xlsx differ diff --git a/test_output2/01_T3田块单元工程计量报验单.xlsx b/test_output2/01_T3田块单元工程计量报验单.xlsx new file mode 100644 index 0000000..37b33c9 Binary files /dev/null and b/test_output2/01_T3田块单元工程计量报验单.xlsx differ diff --git a/test_output2/02_T3田块单元工程工序工程量统计表.xlsx b/test_output2/02_T3田块单元工程工序工程量统计表.xlsx new file mode 100644 index 0000000..c137eb4 Binary files /dev/null and b/test_output2/02_T3田块单元工程工序工程量统计表.xlsx differ diff --git a/test_output2/03.01_清理表土工序工程量签证.xlsx b/test_output2/03.01_清理表土工序工程量签证.xlsx new file mode 100644 index 0000000..aafe899 Binary files /dev/null and b/test_output2/03.01_清理表土工序工程量签证.xlsx differ diff --git a/test_output2/03.02_修平田地工序工程量签证.xlsx b/test_output2/03.02_修平田地工序工程量签证.xlsx new file mode 100644 index 0000000..a611701 Binary files /dev/null and b/test_output2/03.02_修平田地工序工程量签证.xlsx differ diff --git a/test_output2/03.03_田埂修筑工序工程量签证.xlsx b/test_output2/03.03_田埂修筑工序工程量签证.xlsx new file mode 100644 index 0000000..539e59d Binary files /dev/null and b/test_output2/03.03_田埂修筑工序工程量签证.xlsx differ diff --git a/test_output3/01_T3田块单元工程计量报验单.xlsx b/test_output3/01_T3田块单元工程计量报验单.xlsx new file mode 100644 index 0000000..769df0b Binary files /dev/null and b/test_output3/01_T3田块单元工程计量报验单.xlsx differ diff --git a/test_output3/02_T3田块单元工程工序工程量统计表.xlsx b/test_output3/02_T3田块单元工程工序工程量统计表.xlsx new file mode 100644 index 0000000..783cdec Binary files /dev/null and b/test_output3/02_T3田块单元工程工序工程量统计表.xlsx differ diff --git a/test_output3/03.01_清理表土工序工程量签证.xlsx b/test_output3/03.01_清理表土工序工程量签证.xlsx new file mode 100644 index 0000000..1ec508a Binary files /dev/null and b/test_output3/03.01_清理表土工序工程量签证.xlsx differ diff --git a/test_output3/03.02_修平田地工序工程量签证.xlsx b/test_output3/03.02_修平田地工序工程量签证.xlsx new file mode 100644 index 0000000..6c83f84 Binary files /dev/null and b/test_output3/03.02_修平田地工序工程量签证.xlsx differ diff --git a/test_output3/03.03_田埂修筑工序工程量签证.xlsx b/test_output3/03.03_田埂修筑工序工程量签证.xlsx new file mode 100644 index 0000000..b9a748d Binary files /dev/null and b/test_output3/03.03_田埂修筑工序工程量签证.xlsx differ diff --git a/test_output4/01_T3田块单元工程计量报验单.xlsx b/test_output4/01_T3田块单元工程计量报验单.xlsx new file mode 100644 index 0000000..afd37e0 Binary files /dev/null and b/test_output4/01_T3田块单元工程计量报验单.xlsx differ diff --git a/test_output4/02_T3田块单元工程工序工程量统计表.xlsx b/test_output4/02_T3田块单元工程工序工程量统计表.xlsx new file mode 100644 index 0000000..0f9dd29 Binary files /dev/null and b/test_output4/02_T3田块单元工程工序工程量统计表.xlsx differ diff --git a/test_output4/03.01_清理表土工序工程量签证.xlsx b/test_output4/03.01_清理表土工序工程量签证.xlsx new file mode 100644 index 0000000..36508e1 Binary files /dev/null and b/test_output4/03.01_清理表土工序工程量签证.xlsx differ diff --git a/test_output4/03.02_修平田地工序工程量签证.xlsx b/test_output4/03.02_修平田地工序工程量签证.xlsx new file mode 100644 index 0000000..37c65a0 Binary files /dev/null and b/test_output4/03.02_修平田地工序工程量签证.xlsx differ diff --git a/test_output4/03.03_田埂修筑工序工程量签证.xlsx b/test_output4/03.03_田埂修筑工序工程量签证.xlsx new file mode 100644 index 0000000..f29388e Binary files /dev/null and b/test_output4/03.03_田埂修筑工序工程量签证.xlsx differ diff --git a/test_output5/01_T3田块单元工程计量报验单.xlsx b/test_output5/01_T3田块单元工程计量报验单.xlsx new file mode 100644 index 0000000..74575e0 Binary files /dev/null and b/test_output5/01_T3田块单元工程计量报验单.xlsx differ diff --git a/test_output5/02_T3田块单元工程工序工程量统计表.xlsx b/test_output5/02_T3田块单元工程工序工程量统计表.xlsx new file mode 100644 index 0000000..369a430 Binary files /dev/null and b/test_output5/02_T3田块单元工程工序工程量统计表.xlsx differ diff --git a/test_output5/03.01_清理表土工序工程量签证.xlsx b/test_output5/03.01_清理表土工序工程量签证.xlsx new file mode 100644 index 0000000..8a7e89e Binary files /dev/null and b/test_output5/03.01_清理表土工序工程量签证.xlsx differ diff --git a/test_output5/03.02_修平田地工序工程量签证.xlsx b/test_output5/03.02_修平田地工序工程量签证.xlsx new file mode 100644 index 0000000..68adfd9 Binary files /dev/null and b/test_output5/03.02_修平田地工序工程量签证.xlsx differ diff --git a/test_output5/03.03_田埂修筑工序工程量签证.xlsx b/test_output5/03.03_田埂修筑工序工程量签证.xlsx new file mode 100644 index 0000000..48e9713 Binary files /dev/null and b/test_output5/03.03_田埂修筑工序工程量签证.xlsx differ diff --git a/test_v2_output/01_水浇地15~25°区域分部工程工程量汇总表.xlsx b/test_v2_output/01_水浇地15~25°区域分部工程工程量汇总表.xlsx new file mode 100644 index 0000000..87c2686 Binary files /dev/null and b/test_v2_output/01_水浇地15~25°区域分部工程工程量汇总表.xlsx differ diff --git a/test_v2_output/02_T15_T15田块单元工程工序工程量统计表.xlsx b/test_v2_output/02_T15_T15田块单元工程工序工程量统计表.xlsx new file mode 100644 index 0000000..edaf1a5 Binary files /dev/null and b/test_v2_output/02_T15_T15田块单元工程工序工程量统计表.xlsx differ diff --git a/test_v2_output/02_T15_T15田块单元工程计量报验单.xlsx b/test_v2_output/02_T15_T15田块单元工程计量报验单.xlsx new file mode 100644 index 0000000..89b715a Binary files /dev/null and b/test_v2_output/02_T15_T15田块单元工程计量报验单.xlsx differ diff --git a/test_v2_output/02_T15_修平田地工序工程量签证.xlsx b/test_v2_output/02_T15_修平田地工序工程量签证.xlsx new file mode 100644 index 0000000..8dbdb8f Binary files /dev/null and b/test_v2_output/02_T15_修平田地工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T15_清理表土工序工程量签证.xlsx b/test_v2_output/02_T15_清理表土工序工程量签证.xlsx new file mode 100644 index 0000000..2de04f2 Binary files /dev/null and b/test_v2_output/02_T15_清理表土工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T15_田埂修筑工序工程量签证.xlsx b/test_v2_output/02_T15_田埂修筑工序工程量签证.xlsx new file mode 100644 index 0000000..994d9fc Binary files /dev/null and b/test_v2_output/02_T15_田埂修筑工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T16_T16田块单元工程工序工程量统计表.xlsx b/test_v2_output/02_T16_T16田块单元工程工序工程量统计表.xlsx new file mode 100644 index 0000000..274cb02 Binary files /dev/null and b/test_v2_output/02_T16_T16田块单元工程工序工程量统计表.xlsx differ diff --git a/test_v2_output/02_T16_T16田块单元工程计量报验单.xlsx b/test_v2_output/02_T16_T16田块单元工程计量报验单.xlsx new file mode 100644 index 0000000..d6e7257 Binary files /dev/null and b/test_v2_output/02_T16_T16田块单元工程计量报验单.xlsx differ diff --git a/test_v2_output/02_T16_修平田地工序工程量签证.xlsx b/test_v2_output/02_T16_修平田地工序工程量签证.xlsx new file mode 100644 index 0000000..daa17a5 Binary files /dev/null and b/test_v2_output/02_T16_修平田地工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T16_清理表土工序工程量签证.xlsx b/test_v2_output/02_T16_清理表土工序工程量签证.xlsx new file mode 100644 index 0000000..b905dc4 Binary files /dev/null and b/test_v2_output/02_T16_清理表土工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T16_田埂修筑工序工程量签证.xlsx b/test_v2_output/02_T16_田埂修筑工序工程量签证.xlsx new file mode 100644 index 0000000..d7f6ec0 Binary files /dev/null and b/test_v2_output/02_T16_田埂修筑工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T22_T22田块单元工程工序工程量统计表.xlsx b/test_v2_output/02_T22_T22田块单元工程工序工程量统计表.xlsx new file mode 100644 index 0000000..7ce1ae3 Binary files /dev/null and b/test_v2_output/02_T22_T22田块单元工程工序工程量统计表.xlsx differ diff --git a/test_v2_output/02_T22_T22田块单元工程计量报验单.xlsx b/test_v2_output/02_T22_T22田块单元工程计量报验单.xlsx new file mode 100644 index 0000000..867fc32 Binary files /dev/null and b/test_v2_output/02_T22_T22田块单元工程计量报验单.xlsx differ diff --git a/test_v2_output/02_T22_修平田地工序工程量签证.xlsx b/test_v2_output/02_T22_修平田地工序工程量签证.xlsx new file mode 100644 index 0000000..b154030 Binary files /dev/null and b/test_v2_output/02_T22_修平田地工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T22_清理表土工序工程量签证.xlsx b/test_v2_output/02_T22_清理表土工序工程量签证.xlsx new file mode 100644 index 0000000..b9fd0a2 Binary files /dev/null and b/test_v2_output/02_T22_清理表土工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T22_田埂修筑工序工程量签证.xlsx b/test_v2_output/02_T22_田埂修筑工序工程量签证.xlsx new file mode 100644 index 0000000..bdc388f Binary files /dev/null and b/test_v2_output/02_T22_田埂修筑工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T23_T23田块单元工程工序工程量统计表.xlsx b/test_v2_output/02_T23_T23田块单元工程工序工程量统计表.xlsx new file mode 100644 index 0000000..df1f24d Binary files /dev/null and b/test_v2_output/02_T23_T23田块单元工程工序工程量统计表.xlsx differ diff --git a/test_v2_output/02_T23_T23田块单元工程计量报验单.xlsx b/test_v2_output/02_T23_T23田块单元工程计量报验单.xlsx new file mode 100644 index 0000000..29381a1 Binary files /dev/null and b/test_v2_output/02_T23_T23田块单元工程计量报验单.xlsx differ diff --git a/test_v2_output/02_T23_修平田地工序工程量签证.xlsx b/test_v2_output/02_T23_修平田地工序工程量签证.xlsx new file mode 100644 index 0000000..84f1fe8 Binary files /dev/null and b/test_v2_output/02_T23_修平田地工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T23_清理表土工序工程量签证.xlsx b/test_v2_output/02_T23_清理表土工序工程量签证.xlsx new file mode 100644 index 0000000..6fa9c58 Binary files /dev/null and b/test_v2_output/02_T23_清理表土工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T23_田埂修筑工序工程量签证.xlsx b/test_v2_output/02_T23_田埂修筑工序工程量签证.xlsx new file mode 100644 index 0000000..89c50d4 Binary files /dev/null and b/test_v2_output/02_T23_田埂修筑工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T35_T35田块单元工程工序工程量统计表.xlsx b/test_v2_output/02_T35_T35田块单元工程工序工程量统计表.xlsx new file mode 100644 index 0000000..4ba13d1 Binary files /dev/null and b/test_v2_output/02_T35_T35田块单元工程工序工程量统计表.xlsx differ diff --git a/test_v2_output/02_T35_T35田块单元工程计量报验单.xlsx b/test_v2_output/02_T35_T35田块单元工程计量报验单.xlsx new file mode 100644 index 0000000..16c8b04 Binary files /dev/null and b/test_v2_output/02_T35_T35田块单元工程计量报验单.xlsx differ diff --git a/test_v2_output/02_T35_修平田地工序工程量签证.xlsx b/test_v2_output/02_T35_修平田地工序工程量签证.xlsx new file mode 100644 index 0000000..ddd635e Binary files /dev/null and b/test_v2_output/02_T35_修平田地工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T35_清理表土工序工程量签证.xlsx b/test_v2_output/02_T35_清理表土工序工程量签证.xlsx new file mode 100644 index 0000000..7e1c2c1 Binary files /dev/null and b/test_v2_output/02_T35_清理表土工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T35_田埂修筑工序工程量签证.xlsx b/test_v2_output/02_T35_田埂修筑工序工程量签证.xlsx new file mode 100644 index 0000000..4f6b67f Binary files /dev/null and b/test_v2_output/02_T35_田埂修筑工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T36_T36田块单元工程工序工程量统计表.xlsx b/test_v2_output/02_T36_T36田块单元工程工序工程量统计表.xlsx new file mode 100644 index 0000000..c748ab9 Binary files /dev/null and b/test_v2_output/02_T36_T36田块单元工程工序工程量统计表.xlsx differ diff --git a/test_v2_output/02_T36_T36田块单元工程计量报验单.xlsx b/test_v2_output/02_T36_T36田块单元工程计量报验单.xlsx new file mode 100644 index 0000000..ea7d74d Binary files /dev/null and b/test_v2_output/02_T36_T36田块单元工程计量报验单.xlsx differ diff --git a/test_v2_output/02_T36_修平田地工序工程量签证.xlsx b/test_v2_output/02_T36_修平田地工序工程量签证.xlsx new file mode 100644 index 0000000..33dfcb9 Binary files /dev/null and b/test_v2_output/02_T36_修平田地工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T36_清理表土工序工程量签证.xlsx b/test_v2_output/02_T36_清理表土工序工程量签证.xlsx new file mode 100644 index 0000000..9772d85 Binary files /dev/null and b/test_v2_output/02_T36_清理表土工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T36_田埂修筑工序工程量签证.xlsx b/test_v2_output/02_T36_田埂修筑工序工程量签证.xlsx new file mode 100644 index 0000000..f78fad5 Binary files /dev/null and b/test_v2_output/02_T36_田埂修筑工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T37_T37田块单元工程工序工程量统计表.xlsx b/test_v2_output/02_T37_T37田块单元工程工序工程量统计表.xlsx new file mode 100644 index 0000000..a2520ad Binary files /dev/null and b/test_v2_output/02_T37_T37田块单元工程工序工程量统计表.xlsx differ diff --git a/test_v2_output/02_T37_T37田块单元工程计量报验单.xlsx b/test_v2_output/02_T37_T37田块单元工程计量报验单.xlsx new file mode 100644 index 0000000..aac4d77 Binary files /dev/null and b/test_v2_output/02_T37_T37田块单元工程计量报验单.xlsx differ diff --git a/test_v2_output/02_T37_修平田地工序工程量签证.xlsx b/test_v2_output/02_T37_修平田地工序工程量签证.xlsx new file mode 100644 index 0000000..3b5ca1a Binary files /dev/null and b/test_v2_output/02_T37_修平田地工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T37_清理表土工序工程量签证.xlsx b/test_v2_output/02_T37_清理表土工序工程量签证.xlsx new file mode 100644 index 0000000..c11e037 Binary files /dev/null and b/test_v2_output/02_T37_清理表土工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T37_田埂修筑工序工程量签证.xlsx b/test_v2_output/02_T37_田埂修筑工序工程量签证.xlsx new file mode 100644 index 0000000..b378561 Binary files /dev/null and b/test_v2_output/02_T37_田埂修筑工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T3_T3田块单元工程工序工程量统计表.xlsx b/test_v2_output/02_T3_T3田块单元工程工序工程量统计表.xlsx new file mode 100644 index 0000000..db92b41 Binary files /dev/null and b/test_v2_output/02_T3_T3田块单元工程工序工程量统计表.xlsx differ diff --git a/test_v2_output/02_T3_T3田块单元工程计量报验单.xlsx b/test_v2_output/02_T3_T3田块单元工程计量报验单.xlsx new file mode 100644 index 0000000..8764b40 Binary files /dev/null and b/test_v2_output/02_T3_T3田块单元工程计量报验单.xlsx differ diff --git a/test_v2_output/02_T3_修平田地工序工程量签证.xlsx b/test_v2_output/02_T3_修平田地工序工程量签证.xlsx new file mode 100644 index 0000000..a5b8ed3 Binary files /dev/null and b/test_v2_output/02_T3_修平田地工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T3_清理表土工序工程量签证.xlsx b/test_v2_output/02_T3_清理表土工序工程量签证.xlsx new file mode 100644 index 0000000..f564bcc Binary files /dev/null and b/test_v2_output/02_T3_清理表土工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T3_田埂修筑工序工程量签证.xlsx b/test_v2_output/02_T3_田埂修筑工序工程量签证.xlsx new file mode 100644 index 0000000..6e21cf4 Binary files /dev/null and b/test_v2_output/02_T3_田埂修筑工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T4_T4田块单元工程工序工程量统计表.xlsx b/test_v2_output/02_T4_T4田块单元工程工序工程量统计表.xlsx new file mode 100644 index 0000000..67835f9 Binary files /dev/null and b/test_v2_output/02_T4_T4田块单元工程工序工程量统计表.xlsx differ diff --git a/test_v2_output/02_T4_T4田块单元工程计量报验单.xlsx b/test_v2_output/02_T4_T4田块单元工程计量报验单.xlsx new file mode 100644 index 0000000..c142b48 Binary files /dev/null and b/test_v2_output/02_T4_T4田块单元工程计量报验单.xlsx differ diff --git a/test_v2_output/02_T4_修平田地工序工程量签证.xlsx b/test_v2_output/02_T4_修平田地工序工程量签证.xlsx new file mode 100644 index 0000000..d564217 Binary files /dev/null and b/test_v2_output/02_T4_修平田地工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T4_清理表土工序工程量签证.xlsx b/test_v2_output/02_T4_清理表土工序工程量签证.xlsx new file mode 100644 index 0000000..16c30a7 Binary files /dev/null and b/test_v2_output/02_T4_清理表土工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T4_田埂修筑工序工程量签证.xlsx b/test_v2_output/02_T4_田埂修筑工序工程量签证.xlsx new file mode 100644 index 0000000..2187577 Binary files /dev/null and b/test_v2_output/02_T4_田埂修筑工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T5_T5田块单元工程工序工程量统计表.xlsx b/test_v2_output/02_T5_T5田块单元工程工序工程量统计表.xlsx new file mode 100644 index 0000000..ffb5155 Binary files /dev/null and b/test_v2_output/02_T5_T5田块单元工程工序工程量统计表.xlsx differ diff --git a/test_v2_output/02_T5_T5田块单元工程计量报验单.xlsx b/test_v2_output/02_T5_T5田块单元工程计量报验单.xlsx new file mode 100644 index 0000000..cb27479 Binary files /dev/null and b/test_v2_output/02_T5_T5田块单元工程计量报验单.xlsx differ diff --git a/test_v2_output/02_T5_修平田地工序工程量签证.xlsx b/test_v2_output/02_T5_修平田地工序工程量签证.xlsx new file mode 100644 index 0000000..bb5a2a4 Binary files /dev/null and b/test_v2_output/02_T5_修平田地工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T5_清理表土工序工程量签证.xlsx b/test_v2_output/02_T5_清理表土工序工程量签证.xlsx new file mode 100644 index 0000000..ac2ed02 Binary files /dev/null and b/test_v2_output/02_T5_清理表土工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T5_田埂修筑工序工程量签证.xlsx b/test_v2_output/02_T5_田埂修筑工序工程量签证.xlsx new file mode 100644 index 0000000..eb739fc Binary files /dev/null and b/test_v2_output/02_T5_田埂修筑工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T65_T65田块单元工程工序工程量统计表.xlsx b/test_v2_output/02_T65_T65田块单元工程工序工程量统计表.xlsx new file mode 100644 index 0000000..23e73eb Binary files /dev/null and b/test_v2_output/02_T65_T65田块单元工程工序工程量统计表.xlsx differ diff --git a/test_v2_output/02_T65_T65田块单元工程计量报验单.xlsx b/test_v2_output/02_T65_T65田块单元工程计量报验单.xlsx new file mode 100644 index 0000000..61e741d Binary files /dev/null and b/test_v2_output/02_T65_T65田块单元工程计量报验单.xlsx differ diff --git a/test_v2_output/02_T65_修平田地工序工程量签证.xlsx b/test_v2_output/02_T65_修平田地工序工程量签证.xlsx new file mode 100644 index 0000000..c967e1b Binary files /dev/null and b/test_v2_output/02_T65_修平田地工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T65_清理表土工序工程量签证.xlsx b/test_v2_output/02_T65_清理表土工序工程量签证.xlsx new file mode 100644 index 0000000..12f6e4f Binary files /dev/null and b/test_v2_output/02_T65_清理表土工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T65_田埂修筑工序工程量签证.xlsx b/test_v2_output/02_T65_田埂修筑工序工程量签证.xlsx new file mode 100644 index 0000000..4c55698 Binary files /dev/null and b/test_v2_output/02_T65_田埂修筑工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T69_T69田块单元工程工序工程量统计表.xlsx b/test_v2_output/02_T69_T69田块单元工程工序工程量统计表.xlsx new file mode 100644 index 0000000..68df01a Binary files /dev/null and b/test_v2_output/02_T69_T69田块单元工程工序工程量统计表.xlsx differ diff --git a/test_v2_output/02_T69_T69田块单元工程计量报验单.xlsx b/test_v2_output/02_T69_T69田块单元工程计量报验单.xlsx new file mode 100644 index 0000000..9dc8b4d Binary files /dev/null and b/test_v2_output/02_T69_T69田块单元工程计量报验单.xlsx differ diff --git a/test_v2_output/02_T69_修平田地工序工程量签证.xlsx b/test_v2_output/02_T69_修平田地工序工程量签证.xlsx new file mode 100644 index 0000000..e518ac8 Binary files /dev/null and b/test_v2_output/02_T69_修平田地工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T69_清理表土工序工程量签证.xlsx b/test_v2_output/02_T69_清理表土工序工程量签证.xlsx new file mode 100644 index 0000000..7eae8f7 Binary files /dev/null and b/test_v2_output/02_T69_清理表土工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T69_田埂修筑工序工程量签证.xlsx b/test_v2_output/02_T69_田埂修筑工序工程量签证.xlsx new file mode 100644 index 0000000..2d76716 Binary files /dev/null and b/test_v2_output/02_T69_田埂修筑工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T70_T70田块单元工程工序工程量统计表.xlsx b/test_v2_output/02_T70_T70田块单元工程工序工程量统计表.xlsx new file mode 100644 index 0000000..0e611d4 Binary files /dev/null and b/test_v2_output/02_T70_T70田块单元工程工序工程量统计表.xlsx differ diff --git a/test_v2_output/02_T70_T70田块单元工程计量报验单.xlsx b/test_v2_output/02_T70_T70田块单元工程计量报验单.xlsx new file mode 100644 index 0000000..476c1eb Binary files /dev/null and b/test_v2_output/02_T70_T70田块单元工程计量报验单.xlsx differ diff --git a/test_v2_output/02_T70_修平田地工序工程量签证.xlsx b/test_v2_output/02_T70_修平田地工序工程量签证.xlsx new file mode 100644 index 0000000..bac8f03 Binary files /dev/null and b/test_v2_output/02_T70_修平田地工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T70_清理表土工序工程量签证.xlsx b/test_v2_output/02_T70_清理表土工序工程量签证.xlsx new file mode 100644 index 0000000..be7cbc6 Binary files /dev/null and b/test_v2_output/02_T70_清理表土工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T70_田埂修筑工序工程量签证.xlsx b/test_v2_output/02_T70_田埂修筑工序工程量签证.xlsx new file mode 100644 index 0000000..efb85f4 Binary files /dev/null and b/test_v2_output/02_T70_田埂修筑工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T71_T71田块单元工程工序工程量统计表.xlsx b/test_v2_output/02_T71_T71田块单元工程工序工程量统计表.xlsx new file mode 100644 index 0000000..6cb97ab Binary files /dev/null and b/test_v2_output/02_T71_T71田块单元工程工序工程量统计表.xlsx differ diff --git a/test_v2_output/02_T71_T71田块单元工程计量报验单.xlsx b/test_v2_output/02_T71_T71田块单元工程计量报验单.xlsx new file mode 100644 index 0000000..9b19401 Binary files /dev/null and b/test_v2_output/02_T71_T71田块单元工程计量报验单.xlsx differ diff --git a/test_v2_output/02_T71_修平田地工序工程量签证.xlsx b/test_v2_output/02_T71_修平田地工序工程量签证.xlsx new file mode 100644 index 0000000..4377f28 Binary files /dev/null and b/test_v2_output/02_T71_修平田地工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T71_清理表土工序工程量签证.xlsx b/test_v2_output/02_T71_清理表土工序工程量签证.xlsx new file mode 100644 index 0000000..bd48845 Binary files /dev/null and b/test_v2_output/02_T71_清理表土工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T71_田埂修筑工序工程量签证.xlsx b/test_v2_output/02_T71_田埂修筑工序工程量签证.xlsx new file mode 100644 index 0000000..b531255 Binary files /dev/null and b/test_v2_output/02_T71_田埂修筑工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T72_T72田块单元工程工序工程量统计表.xlsx b/test_v2_output/02_T72_T72田块单元工程工序工程量统计表.xlsx new file mode 100644 index 0000000..e3d99ce Binary files /dev/null and b/test_v2_output/02_T72_T72田块单元工程工序工程量统计表.xlsx differ diff --git a/test_v2_output/02_T72_T72田块单元工程计量报验单.xlsx b/test_v2_output/02_T72_T72田块单元工程计量报验单.xlsx new file mode 100644 index 0000000..5c886ff Binary files /dev/null and b/test_v2_output/02_T72_T72田块单元工程计量报验单.xlsx differ diff --git a/test_v2_output/02_T72_修平田地工序工程量签证.xlsx b/test_v2_output/02_T72_修平田地工序工程量签证.xlsx new file mode 100644 index 0000000..2cb75f9 Binary files /dev/null and b/test_v2_output/02_T72_修平田地工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T72_清理表土工序工程量签证.xlsx b/test_v2_output/02_T72_清理表土工序工程量签证.xlsx new file mode 100644 index 0000000..f2e0e5b Binary files /dev/null and b/test_v2_output/02_T72_清理表土工序工程量签证.xlsx differ diff --git a/test_v2_output/02_T72_田埂修筑工序工程量签证.xlsx b/test_v2_output/02_T72_田埂修筑工序工程量签证.xlsx new file mode 100644 index 0000000..03a475a Binary files /dev/null and b/test_v2_output/02_T72_田埂修筑工序工程量签证.xlsx differ diff --git a/workflow.yaml b/workflow.yaml index f63e5c2..1cc7ccf 100644 --- a/workflow.yaml +++ b/workflow.yaml @@ -1,35 +1,48 @@ name: 土地平整工程竣工结算资料(部分)生成 description: > - 从土地平整工程单项工程结算表中提取清理表土、修平田地、田埂修筑三项工序的工程量, - 自动生成 T3 田块单元工程竣工结算资料套表,包含: - 计量报验单、工序工程量统计表、三份工序工程量签证。 -version: 1.0.0 + 从用户提供的工程量结算前后对比表中提取水浇地15~25°区域各田块的 + 清理表土、修平田地、田埂修筑三项工序的工程量, + 生成分部工程工程量汇总表及各田块的竣工结算资料套表 + (计量报验单、工序工程量统计表、工序工程量签证)。 +version: 2.0.0 author: SuiteForge -tags: [竣工结算, 土地平整, 工程量, 结算资料] +tags: [竣工结算, 土地平整, 工程量, 结算资料, 分部工程] category: 竣工结算 params: - input_path: + input_table_path: type: string required: true desc: > - 用户提供的土地平整工程单项工程工作量结算表路径,支持 .xls / .xlsx 格式。 - 该表格应包含"清理表土""修平田地""田埂修筑"三项工序的工程量。 - 示例:/home/user/data/单项工程结算表.xls + 用户提供的工程量结算前后对比表路径,支持 .xls / .xlsx 格式。 + 该表格应包含"土地平整工程 → 水浇地15~25°区域"下各田块 + (T3~T72 等)的清理表土、修平田地、田埂修筑三项工序的工程量明细。 + 示例:/home/user/data/鸡噜工程量结算前后对比表.xlsx output_dir: type: string required: true desc: > 输出目录路径,生成的竣工结算资料文件存放于此。 示例:/home/user/output/ - field_name: + generate_all_fields: type: string required: false - default: T3田块 + default: "true" desc: > - 单元工程名称,如 T3田块 / T4田块 / T5田块 等。 - 此名称会出现在所有输出文档的标题及相关位置。 - 默认值:T3田块 + 是否生成所有田块的独立竣工结算资料(计量报验单+统计表+3份签证)。 + true=生成全部田块,false=只生成第一个田块。 + 默认值:true + subcontractor_name: + type: string + required: false + desc: > + 承包单位名称,如:昭通市北城建筑工程公司 + 不填则留空,可手动补充。 + contract_section: + type: string + required: false + desc: > + 合同段,如:一标段 sub_project_name: type: string required: false @@ -44,21 +57,6 @@ params: desc: > 单位工程名称,出现在工程量签证文档中。 默认值:田块修筑 - project_name: - type: string - required: false - desc: > - 项目名称,不填则自动从结算表中提取。 - contractor: - type: string - required: false - desc: > - 承包单位名称,不填则自动从结算表中提取。 - contract_section: - type: string - required: false - desc: > - 合同段,不填则自动从结算表中提取或留空。 supervision_company: type: string required: false @@ -82,13 +80,12 @@ steps: type: python script_id: generate params: - input_path: $params.input_path + input_table_path: $params.input_table_path output_dir: $params.output_dir - field_name: $params.field_name + generate_all_fields: $params.generate_all_fields + contractor: $params.subcontractor_name + contract_section: $params.contract_section sub_project_name: $params.sub_project_name unit_engineer_name: $params.unit_engineer_name - project_name: $params.project_name - contractor: $params.contractor - contract_section: $params.contract_section supervision_company: $params.supervision_company project_owner: $params.project_owner