Hướng dẫn sử dụng Python tạo các trường thông tin bắt buộc tối thiểu theo Thông tư 16/2025 BXD
Bảng 1: Các Trường Thuộc Tính Tối Thiểu Bắt Buộc (Metadata Fields)
Các lớp dữ liệu địa lý trong HoSoGIS bắt buộc phải có các trường thuộc tính tối thiểu này
Trường thuộc tính
Mô tả
Kiểu dữ liệu
Độ dài dữ liệu
Quy tắc nhập liệu/Cấu trúc
Nguồn
maThongTinQH
Mã thông tin quy hoạch
TEXT
15
Nhập theo nội dung hướng dẫn cụ thể thực hiện Nghị định số 111/2024/NĐ-CP
maHoSoQH
Mã hồ sơ quy hoạch
TEXT
15
Phải trùng với Mã hồ sơ trong cơ sở dữ liệu số pháp lý (HoSoScan)Cấu trúc: <Mã ĐVHC><Loại QH><x><xx><xxxx>
maDoiTuong
Mã đối tượng
TEXT
100
Cấu trúc: <maHoSoQH>-<Tên lớp>-<ObjectID>
tenDoiTuong
Tên đối tượng
TEXT
100
Tên đối tượng
phanLoai
Phân loại
TEXT
250
Nhập thông tin theo bảng ký hiệu/chú giải của bản vẽ
ghiChu
Ghi chú
TEXT
250
Thông tin ghi chú về đối tượng
*Lưu ý: Ngoài các trường thuộc tính tối thiểu, mỗi lớp dữ liệu địa lý cần phải có các trường thuộc tính bổ sung về thông số chi tiết của đối tượng
import arcpy
# ===========================================================
# Field bắt buộc theo Thông tư 16/2025
# ===========================================================
REQUIRED_FIELDS = [
("maThongTinQH", "TEXT", 15, "Mã thông tin quy hoạch"),
("maHoSoQH", "TEXT", 15, "Mã hồ sơ quy hoạch"),
("maDoiTuong", "TEXT", 100, "Mã đối tượng"),
("tenDoiTuong", "TEXT", 100, "Tên đối tượng"),
("phanLoai", "TEXT", 250, "Phân loại"),
("ghiChu", "TEXT", 250, "Ghi chú")
]
SYSTEM_FIELDS = [
"objectid", "shape", "shape_length", "shape_area",
"x", "y", "point_x", "point_y",
"coordinate_x", "coordinate_y",
"layer"
]
REQUIRED_FIELD_NAMES = [f[0].lower() for f in REQUIRED_FIELDS]
# ===========================================================
# Kiểm tra lớp có cho phép chỉnh sửa schema không
# ===========================================================
def layer_is_editable(fc_path):
try:
if arcpy.Describe(fc_path).isVersioned:
return False
if arcpy.Describe(fc_path).dataType not in ("FeatureClass", "Table"):
return False
if arcpy.Describe(fc_path).datasetType == "FeatureService":
return False
return True
except:
return False
# ===========================================================
# Thêm field
# ===========================================================
def add_required_fields(fc_path):
if not layer_is_editable(fc_path):
print(" ⚠ Bỏ qua (không thể chỉnh sửa schema)")
return
existing = [f.name.lower() for f in arcpy.ListFields(fc_path)]
for field_name, field_type, field_length, alias in REQUIRED_FIELDS:
if field_name.lower() not in existing:
try:
arcpy.AddField_management(
fc_path, field_name, field_type,
field_length=field_length, field_alias=alias
)
print(f" + Thêm field: {field_name}")
except Exception as e:
print(f" ❌ Lỗi khi thêm field {field_name}: {e}")
# ===========================================================
# Xóa field thừa
# ===========================================================
def remove_extra_fields(fc_path):
if not layer_is_editable(fc_path):
return
fields = arcpy.ListFields(fc_path)
delete_list = []
for f in fields:
name = f.name.lower()
if f.required:
continue
if name in SYSTEM_FIELDS:
continue
if name in REQUIRED_FIELD_NAMES:
continue
delete_list.append(f.name)
if delete_list:
try:
arcpy.DeleteField_management(fc_path, delete_list)
print(" − Đã xóa field thừa:", delete_list)
except Exception as e:
print(f" ❌ Lỗi khi xóa field: {e}")
# ===========================================================
# Xử lý toàn bộ layers trong MAP hiện tại
# ===========================================================
def process_all_layers():
aprx = arcpy.mp.ArcGISProject("CURRENT")
m = aprx.activeMap
print("\n=== BẮT ĐẦU CHUẨN HÓA ===\n")
for lyr in m.listLayers():
if lyr.isFeatureLayer:
try:
fc_path = arcpy.Describe(lyr).catalogPath
except:
print(f"\n--- Bỏ qua lớp (không mô tả được): {lyr.name} ---")
continue
print(f"\n--- Xử lý lớp: {lyr.name} ---")
add_required_fields(fc_path)
remove_extra_fields(fc_path)
print("\n=== HOÀN TẤT CHUẨN HÓA ===\n")
# ===========================================================
# Chạy chương trình
# ===========================================================
process_all_layers()
0 Nhận xét