import ezdxf from ezdxf.math import Vec3 import os # ============================================================================== # 1. STYLE & GEOMETRY DEFINITIONS # Based on the analysis of the existing DXF file. # ============================================================================== # --- Column widths for the two types of tables --- TABLE_1_COL_WIDTHS = [15.0, 30.0, 55.0, 10.0, 30.0, 10.0, 10.0, 20.0] # Simplified for main part TABLE_2_COL_WIDTHS = [15.0, 30.0, 55.0, 10.0, 30.0, 10.0, 10.0, 20.0, 47.5, 15.0, 5.0, 25.0, 20.0, 30.0, 5.0, 10.0, 5.0, 15.0, 10.0, 10.0, 5.0, 5.0, 20.0] # --- Row Heights --- DEFAULT_ROW_HEIGHT = 8.0 HEADER_ROW_1_HEIGHT = 5.5 HEADER_ROW_2_HEIGHT = 6.5 # --- Text Style Templates (Height, dX, dY) --- # These represent common text placements within a cell. STYLES = { # Generic styles from content analysis "id_number": (3.50, 5.00, 5.50), "part_code": (3.00, 1.50, 5.50), "name_zh": (3.50, 2.00, 4.00), "name_en": (2.00, 2.00, 7.00), "spec": (3.00, 18.50, 4.00), "quantity": (3.00, 4.00, 5.50), "material": (3.00, 8.50, 5.50), "single_weight": (3.00, 2.00, 6.00), "total_weight": (3.00, 2.00, 6.00), "remark": (3.00, 3.50, 3.50), # Specific Header Styles (from Header Analysis) "header_zh": (3.50, 4.50, 5.50), "header_en": (2.00, 2.00, 4.75), "header_mass_zh": (3.50, 2.50, 5.60), "header_mass_en": (2.00, 8.30, 4.80), } # ============================================================================== # 2. DATA TO BE INSERTED # This would typically come from an Excel file or database. # ============================================================================== TABLE_1_DATA = [ # Each item in the list is a row. # Each item in the row is a cell, containing a list of (style, text) tuples. [ [("id_number", "21")], [("part_code", "N-123-A")], [("name_zh", "新盖板"), ("name_en", "NEW COVER")], [("quantity", "2")], [("material", "S30408")], [("single_weight", "5.1")], [("total_weight", "10.2")], [("remark", "自定义")] ], [ [("id_number", "22")], [("part_code", "N-456-B")], [("name_zh", "新支架"), ("name_en", "NEW BRACKET"), ("spec", "M20x150")], [("quantity", "4")], [("material", "Q235B")], [("single_weight", "2.0")], [("total_weight", "8.0")], [("remark", "")] ], ] TABLE_2_HEADER_DATA = [ # Simplified header based on analysis [ [("header_zh", "件 号")], [("header_zh", "图号或标准号")], [("header_zh", "名 称")], [("header_zh", "数量")], [("header_zh", "材 料")], [("header_mass_zh", "质量"), ("header_mass_en", "MASS(kg)")], [], [("header_zh", "备 注")] ], [ [("header_en", "PARTS .NO.")], [("header_en", "DWG NO. OR STD. NO.")], [("header_en", "PARTS. NAME.")], [("header_en", "QTY.")], [("header_en", "MAT'L'")], [], [], [("header_en", "REMARKS")] ], ] # ============================================================================== # 3. DRAWING LOGIC # ============================================================================== def draw_table(msp, start_pos, col_widths, data_rows): """ Draws a complete table with grid lines and text. Args: msp: Modelspace object from ezdxf. start_pos: Vec3 top-left starting position for the table. col_widths: List of column widths. data_rows: List of rows, where each row is a list of cells. """ current_pos = start_pos.copy() col_x_coords = [current_pos.x] for width in col_widths: col_x_coords.append(col_x_coords[-1] + width) # --- Draw Rows and Text --- for row_data in data_rows: row_y_top = current_pos.y row_y_bottom = row_y_top - DEFAULT_ROW_HEIGHT # Draw horizontal line for the row top msp.add_line((current_pos.x, row_y_top), (col_x_coords[-1], row_y_top)) # Draw vertical lines and add text for each cell for i, cell_data in enumerate(row_data): cell_x_left = col_x_coords[i] cell_x_right = col_x_coords[i+1] # Draw left vertical line for the cell msp.add_line((cell_x_left, row_y_top), (cell_x_left, row_y_bottom)) # Add text entities for the cell for style_key, text_content in cell_data: if not text_content: continue style = STYLES.get(style_key) if not style: print(f"Warning: Style '{style_key}' not found. Skipping text.") continue text_height, dX, dY = style # Calculate absolute position for the text insert_pos = (cell_x_left + dX, row_y_top - dY) msp.add_text( text_content, height=text_height, dxfattribs={ "style": "Standard", "insert": insert_pos, } ) # Draw the rightmost vertical line for the row msp.add_line((col_x_coords[-1], row_y_top), (col_x_coords[-1], row_y_bottom)) # Move to the next row position by creating a new Vec3 object current_pos = Vec3(current_pos.x, row_y_bottom) # Draw the final bottom line of the table msp.add_line((start_pos.x, current_pos.y), (col_x_coords[-1], current_pos.y)) # ============================================================================== # 4. MAIN EXECUTION # ============================================================================== def main(): source_dxf_path = r"C:\Users\83500\久翌\CAD编辑同步excel\测试文件区\04_Test_Files\料表.dxf" output_dxf_path = os.path.join(os.path.dirname(source_dxf_path), "料表_with_inserted_tables.dxf") try: doc = ezdxf.readfile(source_dxf_path) msp = doc.modelspace() except IOError: print(f"Could not read DXF file: {source_dxf_path}") return except ezdxf.DXFStructureError: print(f"Invalid or corrupted DXF file: {source_dxf_path}") return # --- Define where to start drawing the new tables --- # We will use a fixed starting position below the existing content. start_y = 150.0 start_x_1 = 266.0 # Aligns with the first table start_x_2 = 700.0 # Place second table to the right # --- Draw the first table --- print("Drawing Table 1...") table1_start_pos = Vec3(start_x_1, start_y) # Combine header and data for drawing # For this demo, we will create a small table with 2 data rows and a header full_table_1_data = TABLE_1_DATA + TABLE_2_HEADER_DATA draw_table(msp, table1_start_pos, TABLE_1_COL_WIDTHS, full_table_1_data) # --- Draw the second table --- print("Drawing Table 2...") table2_start_pos = Vec3(start_x_2, start_y) # Draw the same table again for demonstration draw_table(msp, table2_start_pos, TABLE_1_COL_WIDTHS, full_table_1_data) # --- Save the modified DXF --- try: doc.saveas(output_dxf_path) print(f"Successfully saved modified DXF to: {output_dxf_path}") except IOError: print(f"Could not save DXF file to: {output_dxf_path}") if __name__ == "__main__": main()