ArcGIS 10.x|PythonでMXDのデータソースを一括置き換え
ArcGIS Desktop 10.x:arcpy.mapping で MXD のデータソース一括置換
現場でよくある「レイヤの参照切れ」を、Pythonだけで安全に “上書き修復” する手順とサンプル。今回の実案件(Set_Data 配下)を題材に、再現性のあるスクリプトと運用のコツをまとめました。
今回の事例(要約)
- 対象ルート:
Q:\R06CHIBA\NARITA\TAKO\KYUKEI\Set_Data - 上書き保存(相対パス維持)+ 同名を BACKUP に退避(同階層に
BACKUPフォルダ作成) - レイヤ名とSHP名を厳密に突き合わせ:
KTAISEKI_3MはKTAISEKI_3M.shpが同じフォルダに存在する時だけ差替え(無ければ何もしない) KIDO_100KNも同様。DM系は色崩れ防止のため非表示化・削除はしない(既存の正規パスが生きていれば再接続のみ)- 右クリック実行(UTF-8)メニューからワンクリックで動かせる設計
置換ルール(今回案件)
| レイヤ名 | 期待ファイル | 無い場合 | 備考 |
|---|---|---|---|
KTAISEKI_3M | ./KTAISEKI_3M.shp | 触らない(残置) | ダミー生成・誤接続を禁止 |
KIDO_100KN | ./KIDO_100KN.shp | 触らない(残置) | 同フォルダにある時のみ差替え |
| DM/ラスタ | 既存パス | 触らない | 正規の共通ベースから再接続のみ |
実運用スクリプト(短縮版・そのまま動作)
ArcGIS Desktop 10.4 / Python 2.7。MXDと同じフォルダに対象SHPがある時だけ置換します。ログはUTF-8、コンソールはASCIIに落として出力します。
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import os, io, sys, datetime
import arcpy
FS = sys.getfilesystemencoding() or 'mbcs'
def U(x): # console-safe printable
try:
s = x if isinstance(x, unicode) else x.decode(FS, 'replace')
return s.encode('ascii', 'replace') # console print safe
except:
return '[?]'
ROOT = r"Q:\R06CHIBA\NARITA\TAKO\KYUKEI\Set_Data"
BACKUP = os.path.join(ROOT, "BACKUP")
if not os.path.isdir(BACKUP):
os.makedirs(BACKUP)
log = io.open(os.path.join(ROOT, "rebuild_set_data.log"), "a", encoding="utf-8")
def writelog(msg):
log.write(msg + u"\n")
try:
print(U(msg))
except:
pass
TARGET_RULES = {
u"KTAISEKI_3M" : "KTAISEKI_3M.shp",
u"KIDO_100KN" : "KIDO_100KN.shp",
}
writelog(u"=== 再構築開始: {} ===".format(datetime.datetime.now()))
for root, dirs, files in os.walk(ROOT):
for f in files:
if not f.lower().endswith(".mxd"):
continue
mxd_path = os.path.join(root, f)
writelog(u"[MXD] {}".format(mxd_path))
try:
mxd = arcpy.mapping.MapDocument(mxd_path)
except Exception as e:
writelog(u" NG 読込失敗: {}".format(e))
continue
changed = 0
for df in arcpy.mapping.ListDataFrames(mxd):
for lyr in arcpy.mapping.ListLayers(mxd, "", df):
if lyr.isGroupLayer:
continue
rule = TARGET_RULES.get(lyr.name)
if not rule:
continue
shp_abs = os.path.join(os.path.dirname(mxd_path), rule)
if arcpy.Exists(shp_abs):
try:
lyr.replaceDataSource(os.path.dirname(shp_abs),
"SHAPEFILE_WORKSPACE",
os.path.splitext(os.path.basename(shp_abs))[0],
True)
changed += 1
writelog(u" OK 置換: {} -> ./{}".format(lyr.name, rule))
except Exception as e:
writelog(u" NG 置換失敗: {} :: {}".format(lyr.name, e))
else:
writelog(u" SKIP: {} は同フォルダに無し".format(lyr.name))
# バックアップ退避+上書き保存(相対パス維持)
try:
bak = os.path.join(BACKUP, f)
mxd.saveACopy(bak)
mxd.relativePaths = True
mxd.save()
writelog(u" 保存: 上書き完了 changed={}".format(changed))
except Exception as e:
writelog(u" NG 保存失敗: {}".format(e))
finally:
del mxd
writelog(u"=== 再構築終了 ===")
log.close()
ポイント
- 検索は「MXDと同じフォルダ」だけ。だから 誤って別区画のSHPへ接続しない。
- 存在しない場合は何もしない(ダミー生成・隣のフォルダ探索もしない)。
- 保存は相対パスを維持。既存MXDはBACKUPにコピー。
右クリック実行(UTF-8)メニュー(任意)
レジストリに1回登録すれば、右クリック→ArcGIS 10.4 で実行(UTF-8) から起動できます。
@echo off
reg add "HKCU\Software\Classes\SystemFileAssociations\.py\shell\RunWithArcGIS104" /ve /d "ArcGIS 10.4 で実行(UTF-8)" /f
reg add "HKCU\Software\Classes\SystemFileAssociations\.py\shell\RunWithArcGIS104\command" /ve ^
/d "cmd.exe /d /k chcp 65001 <nul ^& set PYTHONIOENCODING=utf-8 ^& "C:\Python27\ArcGIS10.4\python.exe" "%1" ^& pause" /f
echo 追加しました。
トラブルシュート実例
- コンソールで文字化け / Illegal byte sequence:
printはASCIIに落として出力、ログはUTF-8で書く(上のU()参照)。 - 一部だけリンク復旧しない:今回のロジックは「MXDと同じフォルダにある時だけ置換」。別階層にしかデータが無いレイヤは 仕様どおりスキップ。
- DM系が全部リンク切れ:DMやラスタは「既存パスの再接続のみ・無ければ放置」。必要に応じて
LAYER_RULESを追加し、正規の共通ベースへ差し替える。
実務でよく使う編集・自動化 20例(超コンパクト)
1. データソース置換mapping
lyr.replaceDataSource()2. 相対パス化mapping
mxd.relativePaths=True; mxd.save()3. レイヤ非表示/凡例除外
lyr.visible=False; lyr.showInLegend=False4. 0件レイヤの処置
arcpy.GetCount_management(lyr)→削除/非表示5. グループ整理
arcpy.mapping.AddLayer() / Remove6. ラベルON/OFF
lyr.showLabels=True7. 定義クエリ設定
lyr.definitionQuery="TYPE='A'"8. フィールド可視/順序
arcpy.mapping.ListFields+更新9. シンボル読み替え
レイヤファイル(
レイヤファイル(
.lyr)で UpdateLayer10. レイアウト要素の文字更新
ListLayoutElements(...,"TEXT_ELEMENT")11. 図郭の自動回転/縮尺
df.rotation, df.scale12. 出図の一括PDF化
arcpy.mapping.ExportToPDF()13. 画像出力(PNG/TIFF)
ExportToPNG/TIFF14. ブックマーク巡回
ListBookmarks→中心移動→出力15. レイヤ存在チェック
名前→辞書化して差異検出
名前→辞書化して差異検出
16. マップシリーズもどき
グリッドIDをクエリに流して連番出図
グリッドIDをクエリに流して連番出図
17. 文字スタイル一括変更
テキスト要素→フォント/サイズ更新
テキスト要素→フォント/サイズ更新
18. 複数MXDの監査
データソース一覧をCSV出力
データソース一覧をCSV出力
19. 破損対策バックアップ
saveACopy() で世代管理20. 10.0–10.8互換の安全運転
使える引数を最小に、例外は握りつぶさずログ化
使える引数を最小に、例外は握りつぶさずログ化
なぜ「できた図葉 / できない図葉」が出る?
- 本稿のサンプルは「MXDと同じフォルダにデータがある時だけ置換」=誤接続を防ぐため。
- 別階層にしかないデータはあえてスキップ。必要なら探索ルール(親・兄弟フォルダを順に探す等)を足してください。
おわりに
「何があってもダミー生成しない/むやみに探しに行かない」ポリシーに徹すると、事故は激減します。必要最小限から始めて、現場の規約に合わせて探索ルールを段階的に拡張していくのがコツです。
© Your Team — ArcGIS Desktop 10.x / Python 2.7 実務メモ
コメント
コメントを投稿