콘텐츠로 이동

전송 · 배포

Central File Cloner

중앙파일 1개를 여러 경로에 새 중앙파일로 복제 (한 번 돌리면 여러 건물·지역용 중앙파일 자동 생성)

🖱 쓰는 법

  1. YoonDream 탭 → Admin 패널 → Central File Cloner 버튼 클릭
  2. Select 버튼으로 복제할 원본 중앙파일 지정
    • 워크셰어링 상태를 자동 검증 (녹색 뱃지 ✓ Workshared = OK)
  3. 대상 경로 추가
    • Add Folder — 폴더 하나 선택
    • Add Multiple — 부모 폴더 선택 후 하위 폴더 다중 선택 (한 번에 여러 건물 추가)
  4. 각 경로 옆 파일명 편집
    • 기본은 원본 파일명, 필요 시 "STR_Building-A" 처럼 개별 수정
    • .rvt 확장자는 자동 부착
  5. Run 클릭 → 경로마다 순차 복제

💡 이럴 때 쓰세요

  • 템플릿 1개를 10개 건물별 중앙파일로 한 번에 세팅하고 싶을 때 (Building-A, B, C ... 자동 생성)
  • 폴더 구조는 만들어 뒀는데 중앙파일을 각각 복제해 넣어야 할 때 — Add Multiple 로 폴더 전부 한 번에 추가
  • 권한 반납까지 자동으로 처리해야 할 때 — SaveAs 후 Sync + Relinquish 가 자동으로 실행되어 바로 팀원이 사용 가능한 상태로 남음

복제 원본은 워크셰어링 파일이어야 합니다

워크셰어링이 아닌 파일은 빨간 뱃지로 표시되고 복제 불가. 먼저 "Make Workshared"로 전환 필요.

🔍 UI 미리보기

Central File Cloner
Select\\Server\BIM\Template\STR_Standard.rvt
✓ Workshared워크셋 3개
📁 대상 경로3개
Add FolderAdd MultipleRemove
\\Server\BIM\Bldg-A\STR_Building-A.rvt
\\Server\BIM\Bldg-B\STR_Building-B.rvt
\\Server\BIM\Bldg-C\STR_Building-C.rvt
Developed by Yoon DreamCancel Run
🔧 개발자 정보 (API · 경로 · 내부 로직)

파일 위치

  • Admin.panel/central_file_cloner.pushbutton/ — script.py, ui.xaml
  • Revit 2024 대상

API 처리 흐름 (대상 경로마다 반복)

1. OpenDocumentFile(modelPath, openOpts)  — DetachAndPreserveWorksets
2. SaveAs(newPath, saveOpts)              — WorksharingSaveAsOptions.SaveAsCentral = True
3. SynchronizeWithCentral()               — RelinquishOptions(True) 권한 전체 반납
4. Close(False)                           — 저장 없이 닫기

소스 파일 검증

BasicFileInfo.Extract(path)로 워크셰어링 상태 확인:

  • Workshared → 녹색 뱃지, 복제 가능
  • Non-workshared → 빨간 뱃지, 복제 불가 경고

대상 폴더 관리

기능 설명
Add Folder 단일 폴더 선택
Add Multiple 부모 폴더 선택 → 하위 폴더 다중 선택 (SelectFromList)
파일명 자동 감지 대상 폴더 내 기존 .rvt 파일명을 자동 읽어 표시
파일명 편집 텍스트박스에서 개별 편집 가능, .rvt 자동 추가

핵심 Revit API

API 용도
BasicFileInfo.Extract() 워크셰어링 상태 사전 확인
OpenOptions + DetachFromCentralOption Detach 모드 열기
SaveAsOptions + WorksharingSaveAsOptions 새 중앙파일로 저장
SynchronizeWithCentralOptions + RelinquishOptions 동기화 + 권한 반납

시스템타입 전송

컨테이너 파일에서 벽/바닥/천장/지붕 타입을 선택해 여러 RVT에 한 번에 복사

🖱 쓰는 법

  1. YoonDream 탭 → Admin 패널 → 시스템타입 전송 버튼 클릭
  2. 📄 소스 컨테이너 지정 — 보낼 타입들이 있는 .rvt
  3. 카테고리 필터 버튼 클릭 (전체 · 벽 · 바닥 · 천장 · 지붕)
  4. 보낼 타입 체크 (색상 뱃지로 카테고리 구분)
  5. 📁 타겟 RVT 폴더 선택 → 대상 파일 체크
  6. 🚀 전송 시작 클릭

💡 이럴 때 쓰세요

  • 표준 벽·바닥 타입을 50개 파일에 배포하고 싶을 때 — Transfer Project Standards 배치 버전
  • 카테고리별로 걸러서만 보내고 싶을 때 — "벽만 전체 전송" 같은 작업
  • 이미 있는 타입은 덮어쓰지 않고 새 타입만 추가되길 바랄 때 — 동일 이름 타입 자동 스킵

같은 이름 타입은 자동 스킵

타겟에 이미 있는 동일 이름 타입은 건드리지 않고 새 타입만 추가됩니다. 기존 작업 내용이 덮어쓰이는 걱정 없음.

🔍 UI 미리보기

시스템타입 전송
📄 소스 컨테이너
전체바닥천장지붕
RC200
RC300
바닥SLAB-200
천장CLG-GRID
📁 타겟 RVT
📂 폴더 선택
Building-A.rvt245MB
Building-B.rvt189MB
Building-C.rvt156MB
Developed by Yoon Dream닫기 🚀 전송 시작
🔧 개발자 정보 (API · 경로 · 내부 로직)

파일 위치

  • Admin.panel/system_type_transfer.pushbutton/ — script.py, ui.xaml

대상 시스템 타입 클래스

SYSTEM_TYPE_CLASSES = [
    (WallType,    "벽"),    # 색상: #E53E3E
    (FloorType,   "바닥"),  # 색상: #38A169
    (CeilingType, "천장"),  # 색상: #3182CE
    (RoofType,    "지붕"),  # 색상: #D69E2E
]

전송 메커니즘

ElementTransformUtils.CopyElements(sourceDoc, elementIds, targetDoc, Transform.Identity, CopyPasteOptions())

  • 크로스 문서 복사 (Transaction 필요)
  • 동일 이름 타입이 타겟에 이미 있으면 자동 스킵
  • WarningSwallower — 비치명적 경고 자동 무시

카테고리 필터 UI

전체 / 벽 / 바닥 / 천장 / 지붕 버튼으로 즉시 필터링. 카테고리별 색상 뱃지.


로더블패밀리 일괄로더

기준 파일의 패밀리를 여러 RVT에 한 번에 갈아끼우기 — 파라미터는 '컨테이너 값으로 덮어쓰기'와 '타겟 원래 값 유지' 중에서 항목마다 골라서

🖱 쓰는 법

  1. YoonDream 탭 → Admin 패널 → 패밀리 일괄로더 버튼 클릭
  2. 컨테이너 지정 — 갈아끼울 패밀리들이 들어있는 기준 .rvt (또는 열린 문서)
  3. 🏠 패밀리 목록에서 보낼 패밀리 체크
  4. 📁 타겟 RVT 추가 → 체크
  5. ⚙ 파라미터 설정 (선택)
    • 📥 복사할 파라미터 — 기준 파일 값으로 덮어쓸 항목 고르기
    • 🔒 기존 값 유지 — 타겟에 입력해둔 값을 그대로 둘 항목 고르기 (예: 폭, 길이)
  6. 🚀 작업 시작 클릭 → 타겟마다 패밀리 교체 + 위에서 정한 대로 값 처리

💡 이럴 때 쓰세요

  • 표준 패밀리 여러 개를 수십~수백 개 파일에 한꺼번에 업데이트해야 할 때
  • 대부분은 기준 파일 값으로 통일하되, 일부 값(폭·길이 등)은 각 파일에 입력해둔 걸 살리고 싶을 때 — 항목별로 "덮어쓰기 / 유지" 지정
  • 일반모델로 만든 패밀리를 구조기초 등 다른 분류로 바꿔 끼울 때 — 분류가 바뀌면서 초기화되는 값도 "기존 값 유지"로 지킬 수 있음

복사 vs 유지 — 한 항목을 둘 다 고르면?

같은 항목을 '복사'와 '유지' 양쪽에 체크하면, 작업 직전에 알림이 뜨고 '유지'가 우선됩니다 (기준 파일 값으로 덮지 않고 타겟 원래 값을 지킴). 실수로 둘 다 골라도 안전합니다.

재질 같은 값도 이름으로 맞춰 연동됩니다

재질은 파일마다 내부 번호가 달라서 그냥 옮기면 어긋납니다. 이 도구는 재질 이름으로 타겟에서 같은 재질을 찾아 연결합니다. 타겟에 같은 이름 재질이 없으면 리포트에 "미연동"으로 알려줍니다.

이미 열어둔 파일은 저장하지 않습니다 — 마음껏 실험

지금 Revit에 열어둔 파일을 타겟으로 쓰면, 도구가 자동 저장하지 않습니다. 결과를 보고 직접 저장하거나, 되돌리기(Ctrl+Z) 한 번으로 작업 전으로 돌릴 수 있어 안심하고 시험해 볼 수 있습니다.

📊 작업 후 리포트로 알 수 있는 것

표시 의미
모델 배치 N개 그 패밀리가 모델에 N개 놓여 있어, N개가 실제로 바뀜
타입만(미배치) 패밀리는 들어갔지만 모델엔 안 놓여 있어 형상 변화 없음
실제 모델 갱신 N개 이번 작업으로 모델에서 실제로 바뀐 개수 (건물별 표로도 정리)
🔒 기존 값 유지 N건 타겟 원래 값으로 되돌린 개수

🔍 UI 미리보기

로더블 패밀리 일괄 로더
컨테이너:파일 선택열린 문서STR_Standard_2024.rvt
🏠 패밀리12개
H_Beam_Series구조 보
UC_Column구조 기둥
SD_Single_Door
📁 타겟 RVT3개
Building-A.rvt
Building-B.rvt
Building-C.rvt
📥 복사할 파라미터 설정 재질, 두께 외 39개
🔒 기존 값 유지 설정 Width
Developed by Yoon Dream닫기 🚀 작업 시작

이름에 따옴표(\")가 들어간 패밀리도 정상 처리

RC_RAMP, CONCRETE, L13'-5" 처럼 인치 기호가 든 이름도 그대로 교체됩니다. (내부에서 임시 파일 이름만 안전하게 바꿨다가 원래 이름으로 되돌립니다.)

🔧 개발자 정보 (API · 경로 · 내부 로직)

파일 위치

  • Admin.panel/family_batch_loader.pushbutton/ — script.py, ui.xaml
  • 타겟 1개 처리 = process_target_file() (열기→스냅샷→로드→복사→유지→저장)

두 가지 파라미터 처리 (방향이 반대)

기능 방향 함수
복사할 파라미터 컨테이너 → 타겟 (타입 기준 매칭) copy_params_from_container
기존 값 유지 타겟 로드전 → 로드후 (자기 값 보존) snapshot_family_valuesrestore_family_values

실행 순서: 유지값 스냅샷 → 로드 → 복사 → 유지값 복원(마지막). 복원이 마지막이라 복사·로드 리셋을 모두 이김. 두 목록이 겹치면 effective_copy_names로 복사에서 제외(유지 우선).

패밀리 이름 = .rfa 파일명 (중요)

로드 시 패밀리 이름은 파일명을 따라간다. 이름에 금지문자(")가 있어 임시 파일명을 정제하면 로드 패밀리 이름도 바뀌어 새 패밀리가 생김. → 로드 트랜잭션 안에서 기존 패밀리를 임시 이름으로 pre-rename → 로드 → 원래 이름으로 post-rename(finally 보장). sanitize_filename/rename_family.

빌트인 파라미터는 enum으로 식별

Width 등 빌트인은 LookupParameter(이름)이 동명 읽기전용을 집을 수 있어 실패. 스냅샷에 BuiltInParameter(_param_bip)를 저장하고 복원 시 get_Parameter(bip)로 정확히 되찾음(_find_param_by_identity).

재질(ElementId) 값은 이름으로 변환

ElementId는 문서마다 다른 것을 가리키므로, 복사 시 translate_elementid_by_name으로 컨테이너 요소 이름 → 타겟 동명 요소 ID로 변환. 못 찾으면 "미연동" 리포트.

되돌리기 / 저장

타겟 1개의 모든 변경을 TransactionGroup으로 묶어 Ctrl+Z 한 번에 되돌림(Assimilate, 실패 시 RollBack). 이미 열린 문서는 저장하지 않음(bg_was_open 분기).

모델 영향 집계

로드 전 count_instances_by_family로 배치 인스턴스 수 측정 → "실제 갱신 N개 / 타입만 M개" + 파일별 표.

다이얼로그 처리

핸들러 대상
dismiss_dialog() 모든 다이얼로그 자동 닫기
dismiss_warnings_only() 열기 중 경고만
resolve_failures_on_open() 파일 열기 시 경고 자동 해결

에러 기록: ERROR/family_batch_loader_illegal_path_error.md(이름=파일명), ERROR/family_batch_loader_preserve_builtin_param_error.md(빌트인 enum + 재질 이름변환)


프로젝트정보 전송

소스 RVT의 프로젝트 정보 파라미터(프로젝트 이름·번호·주소 등)를 여러 타겟에 일괄 전송

🖱 쓰는 법

  1. YoonDream 탭 → Admin 패널 → 프로젝트정보 전송 버튼 클릭
  2. 소스 지정 — 기준이 될 프로젝트 정보 담긴 .rvt
  3. 전송할 파라미터 체크
    • 읽기 전용은 자동으로 비활성화
    • ElementId 타입(파일간 호환 안 됨)도 자동 비활성화
  4. 타겟 RVT 추가 → 체크
  5. 전송 클릭 → 각 파일의 프로젝트 정보 갱신

💡 이럴 때 쓰세요

  • 프로젝트 번호·발주처 이름이 변경돼서 100개 파일 모두 수정해야 할 때
  • 주소 · 건물명 등 공통 정보를 기준 파일 하나만 수정하고 나머지에 배포할 때
  • 시트 제목 블록에 자동 연결된 프로젝트 정보를 일괄로 갈아치울 때

읽기 전용 파라미터는 건드리지 않습니다

ReadOnly, ElementId 등 전송이 불안정한 항목은 UI에서 자동 비활성화되어 실수로 깨는 일이 없습니다.

🔍 UI 미리보기

프로젝트정보 전송
📄 소스 RVT
파일 선택열린 문서STR_Master_2026.rvt
전송할 파라미터
프로젝트 이름
프로젝트 번호
발주처
주소
Guid읽기전용
Project LocationElementId
📁 타겟 RVT
폴더 선택
Building-A.rvt
Building-B.rvt
Building-C.rvt
Developed by Yoon Dream닫기 전송
🔧 개발자 정보 (API · 경로 · 내부 로직)

파일 위치

  • Admin.panel/project_info_transfer.pushbutton/ — script.py, ui.xaml

파라미터 분류

속성 처리
ReadOnly 선택 불가, "읽기전용" 뱃지 표시
ElementId 타입 선택 불가 (파일간 ID 불일치)
나머지 (String, Double, Integer) 체크박스로 선택 가능

전송 대상 파라미터 예시

프로젝트 이름, 프로젝트 번호, 주소, 발주처, 건물 이름, 건물 번호 등.


프로젝트표준 일괄전송

🚧 작업 중 — View Template 등 추가 카테고리 예정

Revit Transfer Project Standards의 배치 버전 — 소스 1개를 150개 이상 타겟 파일에 한꺼번에 전송

🖱 쓰는 법

  1. YoonDream 탭 → Admin 패널 → 프로젝트표준 일괄전송 버튼 클릭
  2. 📄 소스 컨테이너 지정 — 표준이 된 .rvt
  3. 보낼 표준 카테고리 체크 (39개 카테고리, 10그룹)
  4. 📁 타겟 RVT 폴더 선택 → 파일 체크
  5. 기존 타입 파라미터 덮어쓰기 체크 여부 결정 (기본 OFF = 스킵)
  6. 🚀 전송 시작 클릭 → 파일 순차 처리 (진행률 표시, 중단 가능)

📂 전송 가능 카테고리 (39개 / 10그룹)

그룹 카테고리 수 대표 항목
Architecture 9 Wall, Floor, Ceiling, Roof, Curtain System 등
Stair/Railing 4 Stairs, Railing 등
Structure 3 Beam System, Rebar Bar, Rebar Cover
Piping 4 Piping System, Pipe, Flex Pipe, Pipe Insulation
Mechanical 5 Mechanical System, Duct, Flex Duct 등
Electrical 2 Conduit, Cable Tray
Annotation 4 Dimension, Text Note, Spot Dimension, Filled Region
Appearance 3 Materials, Line Patterns, Fill Patterns
View 3 View Types, View Filters, Area Schemes
Grid/Level 2 Grid, Level

📂 중복 처리 옵션

모드 동작
스킵 (기본) 타겟에 동일 이름이 이미 있으면 건너뜀 (기존 작업 보존)
덮어쓰기 동일 이름 타입의 파라미터 값을 소스 기준으로 갱신

💡 이럴 때 쓰세요

  • 사내 표준 라이브러리 업데이트 후 모든 프로젝트 파일에 일괄 반영할 때
  • 150개 설비 공종 파일에 MEP 시스템 타입을 한 번에 배포할 때 (실제 검증된 규모)
  • 재질 · 선두께 · 채우기 패턴 등 외형 요소만 일괄 업데이트할 때 — 그룹별로 카테고리 켜고 끌 수 있음
  • 도중에 끊겨도 다시 실행하면 이어서 처리되길 바랄 때 — 이미 처리된 타입은 자동 스킵

대규모 배치용 도구입니다

150+ 파일 대상으로 설계됨. 파일당 시간이 걸리니 가능하면 퇴근 전 실행 · 다음 날 확인 방식 권장. 중단 가능 · 이어하기 지원.

🔍 UI 미리보기

프로젝트 표준 일괄 전송
📄 소스 컨테이너
파일 선택열린 문서
전체 선택전체 해제
ArchitectureWall Types12
MEPPiping System Types8
AnnotationDimension Types5
AppearanceMaterials24
📁 타겟 RVT
폴더 선택열린 문서
Building-A.rvt245MB
Building-B.rvt189MB
Building-C.rvt156MB
기존 타입 파라미터 덮어쓰기
Developed by Yoon Dream닫기 🚀 전송 시작
🔧 개발자 정보 (API · 경로 · 내부 로직)

파일 위치

  • Admin.panel/batchstandardtransfer.pushbutton/ — script.py, ui.xaml, bundle.yaml

전송 카테고리 상세 (39개, 10그룹)

그룹 카테고리
Architecture (9) Wall, Floor, Ceiling, Roof, Curtain System, Building Pad, Slab Edge, Fascia, Gutter
Stair/Railing (4) Stairs, Stairs Run, Stairs Landing, Railing
Structure (3) Beam System, Rebar Bar, Rebar Cover
Piping (4) Piping System, Pipe, Flex Pipe, Pipe Insulation
Mechanical (5) Mechanical System, Duct, Flex Duct, Duct Insulation, Duct Lining
Electrical (2) Conduit, Cable Tray
Annotation (4) Dimension, Text Note, Spot Dimension, Filled Region
Appearance (3) Materials, Line Patterns, Fill Patterns
View (3) View Types, View Filters, Area Schemes
Grid/Level (2) Grid, Level

Revit 버전에 따라 없는 클래스는 동적 import로 자동 제외

전송 메커니즘

시스템타입 전송과 동일한 ElementTransformUtils.CopyElements() 패턴:

  • 동일 이름 타입 → 기본 스킵 (덮어쓰기 옵션 선택 가능)
  • 덮어쓰기 시 ElementId 파라미터 제외 (크로스 문서 무효)
  • WarningSwallower + 3-layer 대화상자 핸들러

대규모 배치 처리 특징

  • 파일당 Open → Transfer → Save/Sync → Close → GC.Collect()
  • 이미 열린 문서 자동 감지 (닫지 않고 재활용)
  • ProgressBar(취소 가능) — 중단 후 재실행 시 스킵 로직으로 자동 이어하기
  • 파일 열기 실패 → 에러 메시지 + 스킵, 다음 파일 계속

교훈: FasciaType 등 Autodesk.Revit.DB 정적 import 실패 시 치명적 에러 → 새 클래스는 반드시 동적 import. Revit 2024에서 설비공종 150개 파일 배치 검증 완료.


시트노트 전파

기준 RVT 시트 위 텍스트 노트를, 동일 시트 번호를 가진 여러 RVT에 한 번에 덮어쓰기로 전파 (표시기·구름 마크는 그대로 보존)

🖱 쓰는 법

  1. YoonDream 탭 → Admin 패널 → 시트노트 전파 버튼 클릭
  2. ① 기준 RVT 지정
    • 파일에서 선택 — 디스크에서 .rvt 고르기
    • 열린 문서에서 — 지금 Revit에 열려있는 파일 중 선택
  3. ② 전파할 시트 체크
    • 시트별로 "노트 N개" 배지 표시되어 어떤 시트가 비어있는지 한눈에 확인
    • 보통 실내마감표 · 기초평면도처럼 모든 파일에 공통으로 있는 시트만 체크
  4. ③ 타겟 RVT 추가
    • 파일 추가 — 디스크에서 직접
    • 폴더 추가 — 하위 모든 RVT 자동 수집 (백업 제외)
    • 열린 문서 추가 — Revit에 이미 열려있는 파일 중 선택
    • 각 파일 옆 상태 배지: 🟧 중앙 / ⬛ 열림 / ⬜ 일반
  5. 전파 실행 클릭 → 최종 확인 다이얼로그 → 진행률 표시 → 결과 리포트

📂 타겟 상태 배지

배지 의미 처리 방식
🟧 중앙 워크쉐어링 중앙파일 로컬 복사본 자동 생성 → 작업 → 동기화 + 권한 반납
열림 이미 Revit에 열려있는 문서 그대로 사용 (저장은 사용자가 직접 — 작업 중인 다른 변경과 섞일 수 있어서)
일반 비워크쉐어링 RVT 백그라운드 열기 → 작업 → 저장 → 닫기

💡 이럴 때 쓰세요

  • 회사 표준 일반주기/시방 노트가 바뀌어서 30개 프로젝트 파일의 실내마감표·기초평면도에 한꺼번에 반영해야 할 때
  • 시트마다 미세하게 다른 노트가 섞여 있어서 한 번에 정리하고 싶을 때 — 기존 텍스트 노트는 모두 지우고 기준 노트로 통일됨
  • 검토자가 달아둔 표시기(Generic Annotation)와 리비전 클라우드는 절대 건드리지 말아야 할 때 — 노트만 골라서 덮어쓰므로 안전
  • 이미 열어둔 작업 파일에도 노트만 추가하고 싶을 때 — 자동으로 감지해서 저장 없이 변경만 적용 (사용자가 확인 후 직접 저장)

기존 텍스트 노트는 모두 삭제됩니다

선택한 시트의 기존 텍스트 노트는 전부 지우고 새 노트로 덮어쓰기합니다. 노트별로 골라서 바꾸는 기능은 아닙니다.

단, 표시기(Generic Annotation)와 리비전 클라우드는 자동으로 보존되므로 검토 코멘트가 날아갈 걱정은 없습니다.

이미 열려있는 파일은 저장을 직접 해주세요

"⬛ 열림" 배지가 붙은 파일은 도구가 노트만 갈아끼우고 저장하지 않습니다. 결과를 확인한 후 본인이 동기화/저장하세요. (도구가 멋대로 저장하면 사용자가 작업 중인 다른 변경사항과 섞일 위험이 있어서)

🔍 UI 미리보기

시트 노트 전파
① 기준 RVT
파일에서 선택열린 문서에서STR_Master_노트기준.rvt
② 전파할 시트2개 선택
A-001실내마감표노트 12개
S-101기초평면도노트 8개
A-1022층 평면도노트 0개
③ 타겟 RVT3개 선택
파일 추가폴더 추가열린 문서 추가
Building-A.rvt중앙
Building-B.rvt열림
Building-C.rvt일반
⚠ 선택한 시트의 기존 텍스트 노트는 모두 삭제 후 덮어쓰기됩니다.
Developed by Yoon Dream취소 전파 실행
🔧 개발자 정보 (API · 경로 · 내부 로직)

파일 위치

  • Admin.panel/sheet_note_propagator.pushbutton/ — script.py, ui.xaml, bundle.yaml
  • lib/snp_note_io.py — TextNote 수집/삭제/크로스 문서 복사 + DuplicateTypeHandler
  • lib/snp_target_runner.py — 중앙파일/로컬복사본/이미 열린 문서 감지 + Save/Sync
  • Revit 2024 대상

TextNote만 정확히 골라내는 핵심 한 줄

collector = FilteredElementCollector(doc, sheet.Id).OfClass(TextNote)
  • 2번째 인자 viewIdOwnerViewId == sheetId만 반환 → 시트에 직접 올린 것만 수집 (뷰포트 내부 노트는 OwnerViewId가 평면뷰 ID이므로 자동 제외)
  • OfClass(TextNote) → Generic Annotation(FamilyInstance)과 Revision Cloud(RevisionCloud)는 별도 클래스이므로 자동 보존

크로스 문서 복사 (좌표 보존)

ElementTransformUtils.CopyElements(
    src_sheet,                       # source ViewSheet
    List[ElementId](src_ids),
    dst_sheet,                       # target ViewSheet (같은 시트 번호)
    Transform.Identity,              # 시트 평면 좌표계 그대로
    copy_opts,                       # DuplicateTypeNamesHandler 포함
)

TextNoteType 충돌 처리

class UseDestinationTypeHandler(IDuplicateTypeNamesHandler):
    def OnDuplicateTypeNamesFound(self, args):
        return DuplicateTypeAction.UseDestinationTypes

동명 타입이 타겟에 이미 있으면 그대로 재사용 → 쓰레기 타입(텍스트 3.5mm 1, 텍스트 3.5mm 2 등) 누적 방지.

타겟 처리 분기

케이스 처리
이미 열린 문서 (find_open_document 매칭) doc 참조 그대로 사용, Save/Sync/Close 절대 금지 — 사용자 직접 처리
중앙파일 (BasicFileInfo.IsCreatedLocal=False) WorksharingUtils.CreateNewLocal → OpenDocumentFile → 작업 → SyncWithCentral(Relinquish=True) → Close
일반 RVT OpenDocumentFile → 작업 → Save → Close

이미 열린 문서 감지 (로컬·중앙 양면 비교)

중앙파일은 열면 Revit이 내부적으로 로컬 경로로 변환하므로, Document.PathName은 로컬 경로를 반환. 사용자가 지정한 원본 경로와 단순 비교하면 미스 → GetWorksharingCentralModelPath()로 중앙 경로 역추적해 양쪽 모두 비교 (copy_sheets_errors.md의 2026-04-04 사건 교훈).

시트 매칭 키

SheetNumber.strip().upper() 정규화 → 'A-101' vs ' a-101 ' 같은 미세 차이 흡수.

Transaction 단위

타겟 1개당 1번의 큰 Transaction (시트 단위가 아닌). 부분 실패 시 그 파일은 원본 그대로 RollBack — 사용자가 안심하고 재시도 가능.

WarningSwallower

Transaction에만 등록되는 IFailuresPreprocessor → 백그라운드 작업 중 워닝 다이얼로그 차단. Sync 전후로는 자동 해제되어 영구 영향 없음.

에러 기록: ERROR/ironpython_unused_dotnet_import_error.md (1건 — System.Windows.Media 미사용 import 함정)