態(tài)屬性表實(shí)現(xiàn)方案與ArcPy腳本實(shí)戰(zhàn))
做測繪、國土、規(guī)劃這一行的肯定都經(jīng)歷過“批量出圖”這件事。分村圖、分幅圖、宗地圖、管線圖一個(gè)項(xiàng)目動(dòng)輒幾十上百張圖面上除了地形和專題要素往往還要求附一張屬性表把圖斑編號、地類名稱、面積、權(quán)屬這些信息列出來。最原始的辦法是出一張圖復(fù)制一段 Excel 粘貼到布局里再手動(dòng)對齊、調(diào)整字號。圖紙少還能忍圖紙一多光是反復(fù)復(fù)制粘貼就能把人逼瘋而且最容易翻車頁面換到下一條村了表格內(nèi)容還停在上一頁檢查的時(shí)候根本看不出來。所謂“動(dòng)態(tài)表格”核心訴求就一句話出圖頁碼切到哪表格內(nèi)容就跟著變到哪不需要人肉同步。這個(gè)需求在 ArcGIS 里完全有辦法解決只是大多數(shù)人被“屬性表怎么塞進(jìn)布局”這一步卡住了。我這些年試過三種主流方案ArcMap/ArcGIS Pro 自帶的表框、ArcPy 腳本來控制、ArcObjects 或 Pro SDK 做插件。這篇就按從易到難的順序把每條路線的原理、配置、坑都講清楚重點(diǎn)說說我個(gè)人最推薦、也最穩(wěn)的“地圖系列 表框 ArcPy 控制”組合方案最后再給一套可以直接復(fù)制的批量出圖腳本。1. 先理清需求“動(dòng)態(tài)表格”到底是要哪種動(dòng)態(tài)很多人一上來就問“怎么把屬性表插到布局里”其實(shí)這個(gè)問題本身不夠準(zhǔn)確。必須先搞清楚你要的“動(dòng)態(tài)”是哪種動(dòng)態(tài)不然方案選型很容易跑偏。1.1 三種典型的批量出圖場景第一類跟著地圖范圍走。這是最常見的分村圖、分幅圖場景。例如每個(gè)行政村出一張土地利用現(xiàn)狀圖圖面上只顯示落在本村范圍內(nèi)的地類圖斑旁邊的屬性表也只需要列出本村的圖斑。頁碼一換表格內(nèi)容就要跟著新的地圖范圍重新篩選。第二類跟著驅(qū)動(dòng)要素走。典型是宗地圖、房產(chǎn)分戶圖。每一頁對應(yīng)一個(gè)宗地表格要顯示的是當(dāng)前宗地自己的權(quán)利人、坐落、面積、用途等信息和地圖范圍內(nèi)的其他要素?zé)o關(guān)。此時(shí)表格其實(shí)是跟著“頁面驅(qū)動(dòng)要素”的某個(gè)唯一標(biāo)識走的。第三類跟著篩選條件走。比如要出一個(gè)項(xiàng)目區(qū)范圍內(nèi)的指定地塊清單出圖順序和表格內(nèi)容都由某個(gè)字段值或選擇集決定和空間范圍不完全重合。這三類需求對應(yīng)的實(shí)現(xiàn)手段并不一樣。第一類用“表框 僅顯示地圖范圍內(nèi)要素”最省事第二類需要在表框和驅(qū)動(dòng)要素之間建立關(guān)聯(lián)第三類往往要寫腳本做自定義過濾甚至匯總統(tǒng)計(jì)。下面討論的所有方案本質(zhì)上都是在解決“表格如何跟著頁面走”這一件事只是技術(shù)深度不同。1.2 為什么不能靠復(fù)制粘貼搞定這個(gè)坑我剛開始也踩過。直接在布局里插入 Excel 表格或者把屬性表截圖貼進(jìn)來當(dāng)時(shí)看著沒問題但有兩個(gè)致命傷。第一個(gè)致命傷是靜態(tài)內(nèi)容不會刷新。數(shù)據(jù)驅(qū)動(dòng)頁面每翻一頁數(shù)據(jù)框的地圖范圍變了而粘貼進(jìn)來的表格還是死的內(nèi)容。要么每頁手動(dòng)改要么導(dǎo)出后合成不管哪種都失去了“批量”的意義而且人肉維護(hù)幾十頁的表格出錯(cuò)率極高。第二個(gè)致命傷是排版不可控。Excel 貼到布局里列寬、行高、字體經(jīng)常會變形字段一多更是災(zāi)難。ArcGIS 布局里的動(dòng)態(tài)表格至少能響應(yīng)頁面大小、可以設(shè)定字體和行高這一點(diǎn)靜態(tài)粘貼完全比不了。所以只要是真正批量出圖動(dòng)態(tài)表格必須走 ArcGIS 自己的布局機(jī)制不能走“復(fù)制粘貼”這條野路子。2. 三條技術(shù)路線的選型分析動(dòng)態(tài)表格的實(shí)現(xiàn)路線我歸納成三條。各自有明確適用邊界沒有絕對的好壞選錯(cuò)了就是給自己挖坑。2.1 原生表框成本最低的動(dòng)態(tài)表格ArcMap 和 ArcGIS Pro 布局里都有“表框”Table Frame這個(gè)元素學(xué)名叫表格框可以在布局中直接插入一個(gè)和圖層綁定的表格。原理很好理解表框內(nèi)部維護(hù)了一個(gè)數(shù)據(jù)源同時(shí)和數(shù)據(jù)框的空間范圍掛鉤只要勾選了“僅顯示地圖范圍內(nèi)的要素”那么地圖范圍一變表格會立即對數(shù)據(jù)源做一次空間篩選只把落在當(dāng)前范圍內(nèi)的要素屬性顯示出來。這個(gè)機(jī)制天然適配第一類場景而且完全不用寫代碼。它的缺點(diǎn)是功能邊界太明顯只能按空間范圍過濾不能做多字段拼接、不能做分組統(tǒng)計(jì)、不能合并多個(gè)圖層的數(shù)據(jù)。如果你需要的只是“把當(dāng)前圖幅范圍內(nèi)的要素屬性列出來”那原生表框就是最優(yōu)解。2.2 ArcPy 腳本兼顧靈活與可控原生表框解決的是 80% 的常規(guī)需求剩下 20% 的定制邏輯就要靠 ArcPy。ArcPy 里有一個(gè)專門操作制圖表達(dá)的空間叫arcpy.mp它可以讀取工程文件、布局、地圖系列、布局元素也能在頁面切換的過程中動(dòng)態(tài)修改表框的可見性、位置、大小甚至改變表框綁定的數(shù)據(jù)源字段。我通常把 ArcPy 定位成“批量控制層”讓腳本代替人手去切換地圖系列的頁面在切換過程中做額外控制最后統(tǒng)一導(dǎo)出圖片或 PDF。它能做到的事情包括某些頁面不顯示表格、某些頁面要換一組字段、導(dǎo)出前臨時(shí)把字號調(diào)小、把表框挪到合適位置等。這些都是原生表框無法自動(dòng)完成的。有人可能會問ArcPy 能不能干脆自己生成一個(gè)表格插到布局里坦白說arcpy.mp沒有提供“創(chuàng)建表框”的接口它只能操作布局里已經(jīng)存在的元素。所以在我的方案里ArcPy 是配合原生表框使用的而不是替代。2.3 ArcObjects / Pro SDK 插件深度定制如果你要的是“一鍵式”體驗(yàn)比如給外業(yè)人員做一個(gè)按鈕點(diǎn)一下自動(dòng)生成多張帶表格的圖件那就得上 ArcObjectsArcMap 時(shí)代或 ArcGIS Pro SDK 了。插件的好處是整套流程可以封裝成一個(gè)工具條或者按鈕表框可以由代碼在布局里動(dòng)態(tài)創(chuàng)建位置、尺寸、樣式完全可控甚至可以做很復(fù)雜的表格內(nèi)容比如合并多張表、計(jì)算匯總行。但代價(jià)也很明顯開發(fā)環(huán)境搭建麻煩需要 Visual Studio需要對著 SDK 文檔查接口部署的時(shí)候還得考慮目標(biāo)機(jī)器有沒有對應(yīng)的運(yùn)行時(shí)環(huán)境。如果只是內(nèi)部項(xiàng)目用我建議優(yōu)先把 ArcPy 方案做成腳本工具而不是一上來就上 SDK。2.4 我的選型建議這里直接給結(jié)論。項(xiàng)目周期緊、需求簡單用原生表框需要在出圖流程里做額外判斷和控制用 ArcPy 包一層要面向非技術(shù)用戶做一鍵工具、對表格形態(tài)要求極高才考慮 SDK。我自己的默認(rèn)組合是布局里做好表框配好地圖系列再用 ArcPy 寫一個(gè)批量控制腳本這可能是投入產(chǎn)出比最高的方案。對比維度原生表框ArcPy 腳本Pro SDK 插件是否需要寫代碼完全不用需要 Python 基礎(chǔ)需要 .NET 開發(fā)經(jīng)驗(yàn)表格動(dòng)態(tài)跟隨地圖范圍支持支持支持自定義字段與樣式有限可動(dòng)態(tài)調(diào)整完全可控創(chuàng)建全新表框手動(dòng)插入不支持創(chuàng)建支持代碼創(chuàng)建部署成本零成本裝有 ArcGIS 即可需要 SDK 環(huán)境適用人群大多數(shù)業(yè)務(wù)人員懂點(diǎn)腳本的技術(shù)人員插件開發(fā)者3. 實(shí)操基于 Map Series 表框的動(dòng)態(tài)屬性表下面進(jìn)入正題把最推薦的那套方案完整走一遍。我用 ArcGIS Pro 的地圖系列Map Series為例ArcMap 的數(shù)據(jù)驅(qū)動(dòng)頁面Data Driven Pages思路完全一致。整個(gè)過程分四步準(zhǔn)備工程、插入表框、用 ArcPy 控制、導(dǎo)出。3.1 準(zhǔn)備工程與地圖系列地圖系列是 ArcGIS Pro 2.x 里的叫法對應(yīng) ArcMap 的 Data Driven Pages。它的核心機(jī)制是指定一個(gè)“驅(qū)動(dòng)圖層”這個(gè)圖層有多少條記錄就得有多少頁頁面每切換一個(gè)頁面地圖范圍會根據(jù)當(dāng)前驅(qū)動(dòng)要素自動(dòng)縮放定位。在 Pro 里操作路徑是布局視圖 - 插入 - 地圖系列。名稱隨便起我習(xí)慣叫“圖幅序列”。關(guān)鍵參數(shù)有三個(gè)。第一個(gè)是驅(qū)動(dòng)圖層。分村圖就選行政村面圖層宗地圖就選宗地面圖層。這個(gè)圖層必須有且僅有一一對應(yīng)的標(biāo)識字段不能有重復(fù)值否則頁面索引會亂。第二個(gè)是空間參考。驅(qū)動(dòng)圖層和數(shù)據(jù)框內(nèi)用來做表格數(shù)據(jù)源的圖層最好使用同一坐標(biāo)系避免因?yàn)橥队稗D(zhuǎn)換產(chǎn)生不必要的邊界偏移。第三個(gè)是頁面范圍定義方式。默認(rèn)是“按要素范圍”也就是每個(gè)頁面自動(dòng)縮放到當(dāng)前驅(qū)動(dòng)要素的外包矩形。我會在范圍里加一個(gè) 5% 到 10% 的外擴(kuò)值不然圖斑貼邊太緊讀圖體驗(yàn)很差。這個(gè)階段不涉及腳本但它是整個(gè)方案的骨架。很多新手第一次跑批量出圖發(fā)現(xiàn)表格內(nèi)容不跟著變九成原因是地圖系列沒有配好或者驅(qū)動(dòng)圖層選錯(cuò)了。3.2 在布局中插入并配置表框地圖系列建好之后開始插表框。在布局選項(xiàng)卡里找到“插入”點(diǎn)擊“表框”會彈出一個(gè)圖層列表選你要顯示的那個(gè)圖層比如地類圖斑面。插入之后要在表框的屬性面板里做三件事。第一件選擇字段。只保留出圖必要的列不要一股腦全選。字段太多一頁表格根本擺不下比例尺地圖上的注釋區(qū)也沒那么大的空間。我一般控制在 6 到 8 列以內(nèi)。第二件設(shè)置“僅顯示地圖范圍內(nèi)的要素”。這個(gè)選項(xiàng)是“動(dòng)態(tài)”的關(guān)鍵開關(guān)它在表框的數(shù)據(jù)源設(shè)置里。如果不勾選表框會把整個(gè)圖層的所有要素屬性全部列出來幾十頁圖都是同樣一堆內(nèi)容。勾選之后表框會自動(dòng)對當(dāng)前頁面地圖范圍內(nèi)可見的要素進(jìn)行過濾。這一步是我們方案能成立的核心原因。第三件調(diào)整樣式。字體、字號、行高、邊框顏色都在表框格式里調(diào)。這一塊看著不起眼實(shí)際上最花時(shí)間。行高太矮中文被截?cái)嘧痔笠豁撝荒芊牌甙诵羞吙蛱?xì)導(dǎo)出的 PDF 放大后發(fā)虛。我的習(xí)慣是先設(shè)置一個(gè)保守的字體大小8 到 10 磅再去調(diào)整列寬讓表格在布局里成一個(gè)規(guī)整的矩形不壓標(biāo)題、不壓圖例。表框插入后在布局元素列表里會有一個(gè)名字比如“表框 1”。這個(gè)名字要留意后面 ArcPy 腳本會用它來定位元素。我建議在屬性面板里直接改名成“屬性表”這樣腳本可讀性更好。3.3 用 ArcPy 批量控制表框與導(dǎo)出現(xiàn)在到了關(guān)鍵環(huán)節(jié)。下面的腳本做的事情是打開工程找到布局確認(rèn)地圖系列被啟用然后逐頁遍歷在每一頁上檢查表框元素控制可見性和基本屬性最后導(dǎo)出 PDF。完整代碼如下。import arcpy import os # 1. 打開工程 aprx_path rD:\projects\批量出圖.aprx project arcpy.mp.ArcGISProject(aprx_path) try: # 2. 獲取目標(biāo)布局和地圖系列 layout project.listLayouts(出圖布局)[0] ms layout.mapSeries if not ms.enabled: raise RuntimeError(當(dāng)前布局未啟用地圖系列請先創(chuàng)建地圖系列) # 3. 獲取布局中的表框元素 table_elm None for elm in layout.listElements(TABLE_FRAME_ELEMENT, 屬性表): table_elm elm break if table_elm is None: raise RuntimeError(布局中未找到名為屬性表的表框元素) # 4. 輸出目錄 output_dir rD:\output\圖件 if not os.path.exists(output_dir): os.makedirs(output_dir) # 5. 遍歷地圖系列的所有頁面 for page_num in range(1, ms.pageCount 1): ms.currentPageNumber page_num # 當(dāng)前頁面對應(yīng)的驅(qū)動(dòng)要素屬性值 page_code ms.pageName # 示例某些頁面不需要顯示屬性表 if page_code.startswith(特殊): table_elm.visible False else: table_elm.visible True # 也可以動(dòng)態(tài)修改表框位置或尺寸 # table_elm.elementPositionX 20 # table_elm.elementPositionY 15 # table_elm.elementWidth 40 # table_elm.elementHeight 30 # 6. 導(dǎo)出當(dāng)前頁面 pdf_path os.path.join(output_dir, f{page_code}.pdf) layout.exportToPDF(pdf_path, resolution300) print(f已導(dǎo)出: {page_code}.pdf) finally: del project每一部分我都解釋一下方便你按自己項(xiàng)目改。project.listLayouts(出圖布局)[0]是按名稱鎖定布局多個(gè)布局的工程里一定要寫清楚名字別取默認(rèn)的“布局”。ms.enabled用來判斷地圖系列是否啟用如果布局里壓根沒有設(shè)置地圖系列mapSeries屬性返回的對象會表現(xiàn)為未啟用腳本里務(wù)必做這個(gè)檢查不然后續(xù)調(diào)用會報(bào)錯(cuò)。layout.listElements(TABLE_FRAME_ELEMENT, 屬性表)是按類型和名稱找表框元素。注意listElements返回的是一個(gè)列表即使只傳了名稱也可能因?yàn)榈谝粋€(gè)參數(shù)和第二個(gè)參數(shù)的匹配邏輯返回空列表所以要做 None 判斷。ms.currentPageNumber page_num是切換頁碼這是整個(gè)動(dòng)態(tài)控制的核心動(dòng)作。每切換一次布局中的數(shù)據(jù)框、表框、圖例都會根據(jù)當(dāng)前驅(qū)動(dòng)要素重新計(jì)算一次。ms.pageName返回當(dāng)前頁面的名稱通常是驅(qū)動(dòng)要素的某個(gè)字段值。用它來做導(dǎo)出文件名圖名自然就對應(yīng)上了不用自己拼字符串。exportToPDF(resolution300)導(dǎo)出當(dāng)前頁。實(shí)際項(xiàng)目里我更常用exportToPDF把所有頁面一次性導(dǎo)出但那個(gè)方式做不到“某些頁面不顯示表”這種逐頁判斷所以需要批量控制時(shí)就用循環(huán)。最后del project放在finally里確保 ArcGIS 進(jìn)程不會因?yàn)楣こ虒ο鬀]有釋放而卡住。3.4 表格排版的細(xì)節(jié)控制腳本寫完了但真正影響成果質(zhì)量的是排版。這個(gè)環(huán)節(jié)沒有捷徑必須把第一頁調(diào)到滿意再批量跑。字段順序上要按業(yè)務(wù)圖的閱讀習(xí)慣排。面積字段一般放在最后而且最好設(shè)置成小數(shù)位兩位字段別名一定要設(shè)置成中文別名不然表格表頭會顯示英文字段名圖審的時(shí)候很難看。字號和行高上A4 橫向版面、300dpi 導(dǎo)出字號 9 到 10 磅比較穩(wěn)。行高不能只調(diào)到文字剛好顯示要留一點(diǎn)余量不然導(dǎo)出的 PDF 在閱讀器里放大會覺得字?jǐn)D成一團(tuán)。中文字體建議用微軟雅黑或宋體西文字體選 Arial不要相信默認(rèn)字體在任何機(jī)器上都能正常顯示。列寬上自動(dòng)列寬其實(shí)很坑。它會讓每一列按內(nèi)容撐開導(dǎo)致同樣一個(gè)表框在不同頁面里忽寬忽窄。我的做法是先在屬性面板里手動(dòng)固定每列寬度尤其是文本類字段寧可稍微寬一點(diǎn)也不要讓它斷行。如果表格實(shí)在放不下首先考慮刪字段而不是縮小字號因?yàn)樽痔柼≡诖蛴「迳细究床磺?。還有一個(gè)細(xì)節(jié)表框的行號列也就是 No. 那一列默認(rèn)會顯示。你要是嫌占地方可以直接在表框?qū)傩岳镪P(guān)掉。另外如果屬性表和圖例在布局里有位置沖突可以像腳本注釋里寫的那樣在遍歷頁面時(shí)動(dòng)態(tài)調(diào)整表框的 X、Y 坐標(biāo)和寬高保證每一頁都不重疊。4. 進(jìn)階把腳本封裝成可雙擊運(yùn)行的插件工具腳本寫出來之后直接扔給同事用是不現(xiàn)實(shí)的。他們不可能打開 PyCharm 改路徑、跑腳本。要把這套東西變成“插件”最簡單的方式是做成 ArcGIS Python 工具箱.pyt / .atbx或者做成普通腳本工具掛到某個(gè)現(xiàn)成的工具箱里。4.1 工具參數(shù)與界面設(shè)計(jì)參數(shù)越少越好。見過很多內(nèi)部工具參數(shù)設(shè)計(jì)得跟高考卷子一樣密密麻麻十幾項(xiàng)同事拿到手第一反應(yīng)是抗拒。我的經(jīng)驗(yàn)是只暴露三個(gè)參數(shù)工程文件路徑、布局名稱、輸出目錄。驅(qū)動(dòng)圖層、表框名稱這些能在腳本里寫死或者在腳本內(nèi)部自動(dòng)探測的就不要讓使用者操心。Python 工具箱的核心結(jié)構(gòu)其實(shí)就是一個(gè)繼承自arcpy.mp.Tool的類里面定義getParameterInfo來聲明參數(shù)execute里放主邏輯。主邏輯就是把 3.3 那套腳本搬進(jìn)去加上arcpy.AddMessage輸出進(jìn)度信息。在 Pro 里這樣的工具可以像原生工具一樣運(yùn)行也能在模型構(gòu)建器里和其他工具串起來。4.2 異常處理與日志工具給同事用之后你會遇到各種意想不到的輸入錯(cuò)誤。工程路徑寫錯(cuò)、布局名寫錯(cuò)、輸出目錄沒有創(chuàng)建權(quán)限這些都要有明確的提示否則對方只會截圖給你說“報(bào)錯(cuò)了”。我的習(xí)慣是在腳本里捕獲具體異常然后轉(zhuǎn)成中文提示消息。下面這段是簡化版的異常處理邏輯try: layout project.listLayouts(layout_name)[0] except IndexError: arcpy.AddError(f布局\{layout_name}\不存在請檢查布局名稱) raise try: ms layout.mapSeries if not ms.enabled: arcpy.AddError(布局未啟用地圖系列請先在地圖系列面板中創(chuàng)建) raise RuntimeError(map series not enabled) except AttributeError: arcpy.AddError(當(dāng)前布局不支持地圖系列請確認(rèn)使用的是布局視圖) raise另外一定要加日志或者進(jìn)度消息。arcpy.AddMessage(f正在導(dǎo)出第 {page_num}/{ms.pageCount} 頁)配合arcpy.SetProgressor能讓使用者在工具窗口里看到進(jìn)度。幾十頁的圖導(dǎo)出可能要幾分鐘沒進(jìn)度提示會讓同事以為死機(jī)了。4.3 與現(xiàn)有檢查工具、超級工具配合實(shí)際項(xiàng)目里批量出圖很少獨(dú)立存在。數(shù)據(jù)從外業(yè)采集回來往往要先做一輪幾何檢查。你可以在出圖前先跑一遍“檢查尖銳角”這類的幾何檢查插件把有尖銳角、自相交、拓?fù)溴e(cuò)誤的要素標(biāo)記出來。然后在屬性表里加一個(gè)“備注”字段把檢查結(jié)果用字段計(jì)算器寫進(jìn)去。這樣出圖時(shí)動(dòng)態(tài)表格里能直接看到哪些要素有問題圖件和質(zhì)檢結(jié)果同步交付省掉多輪來回溝通。如果你的單位有“超級工具”這類綜合性工具箱更理想的做法是把出圖腳本做成其中一個(gè)子工具。用模型構(gòu)建器把“幾何檢查 - 字段計(jì)算 - 批量出圖”串成一個(gè)模型界面只留一個(gè)“開始”按鈕。我給幾個(gè)項(xiàng)目做過類似的流程同事的接受度明顯比單獨(dú)發(fā)腳本高得多。再有就是界面層。如果你們既不想裝 Pro SDK又覺得標(biāo)準(zhǔn)工具對話框不夠直觀現(xiàn)在也可以用 nicegui 這類 Python Web 框架快速搭一個(gè)表單頁面讓使用者在瀏覽器里選擇工程目錄、填寫輸出路徑然后后端調(diào)用 ArcPy。對于一些需要在多個(gè)終端統(tǒng)一發(fā)版的內(nèi)業(yè)小組這種方式比每臺機(jī)器裝插件更好維護(hù)。當(dāng)然這屬于錦上添花核心的批量出圖邏輯還是上面這套。5. 常見問題與排查實(shí)錄這部分是我踩坑踩出來的實(shí)錄。每次在項(xiàng)目上幫別人排錯(cuò)翻來覆去基本就是這幾個(gè)問題。5.1 表格內(nèi)容不隨頁面變化這個(gè)問題的出現(xiàn)頻率最高。最典型的表現(xiàn)是地圖范圍切到下一個(gè)村了表格里還是上一個(gè)村的記錄。原因幾乎都是表框的數(shù)據(jù)源設(shè)置里沒有勾選“僅顯示地圖范圍內(nèi)的要素”。在 ArcGIS Pro 中表框關(guān)聯(lián)圖層后默認(rèn)過濾邏輯未必會啟用空間過濾需要你手動(dòng)到表框?qū)傩岳镎疫@個(gè)選項(xiàng)。另一種可能沒那么明顯表框綁定的是另一個(gè)數(shù)據(jù)框的圖層而不是當(dāng)前地圖系列驅(qū)動(dòng)的那一個(gè)。多數(shù)據(jù)框布局里很容易犯這個(gè)錯(cuò)。檢查方式是在表框?qū)傩岳锟磾?shù)據(jù)源屬于哪個(gè)數(shù)據(jù)框確保和地圖系列、地圖框三者是同一個(gè)鏈路。補(bǔ)充一個(gè)檢查表格的小技巧導(dǎo)出 PDF 之前先在布局視圖里手動(dòng)切換幾個(gè)地圖片專門看表格的“行數(shù)”變化。如果頁面切換后行數(shù)一直在變說明表框的動(dòng)態(tài)過濾已經(jīng)生效可以放心批量導(dǎo)出如果行數(shù)不變那基本就是上面兩個(gè)原因。5.2 要素太多表格放不下這是第二高頻問題。當(dāng)前圖幅范圍內(nèi)要素特別多的時(shí)候表格會自動(dòng)往下延伸超出布局頁面邊界甚至把下方的比例尺和指北針蓋上。我的處理策略是“前端控制 后端兜底”。前端控制就是盡量精簡字段、縮小字號、在布局里給表框固定一個(gè)最大尺寸。后端兜底是指在 ArcPy 腳本里加一個(gè)判斷如果當(dāng)前頁面的表格行數(shù)超過閾值就自動(dòng)把表框的可見性改為 False只保留圖面不保留屬性表。行數(shù)的獲取方式不建議用arcpy.GetCount去查數(shù)據(jù)源那樣得到的是全表數(shù)量不是當(dāng)前頁面過濾后的數(shù)量。更穩(wěn)妥的方法是讀取表框元素的數(shù)據(jù)源然后根據(jù)當(dāng)前地圖范圍做一次空間查詢。如果嫌邏輯復(fù)雜也可以退一步在腳本里讀取當(dāng)前頁面的驅(qū)動(dòng)要素面積面積大說明圖斑多超過一定閾值就讓表框隱藏。這個(gè)屬于經(jīng)驗(yàn)判斷可以在項(xiàng)目里慢慢調(diào)閾值。5.3 字體、中文與樣式問題ArcMap 時(shí)代中文亂碼是個(gè)老問題在 ArcGIS Pro 里已經(jīng)很少見了但導(dǎo)出 PDF 后還是可能有字體發(fā)虛、中文變成方塊的情況。根因是導(dǎo)出的 PDF 沒有嵌入字體。解決辦法有兩個(gè)。一個(gè)是在表框格式里把字體顯式設(shè)置成中文字體比如宋體、黑體、微軟雅黑不要用默認(rèn)的 Esri 字體另一個(gè)是在導(dǎo)出 PDF 時(shí)在exportToPDF參數(shù)里開啟“嵌入字體”相關(guān)的選項(xiàng)。注意某些字體本身不開放嵌入權(quán)限比如一些商業(yè)字體這時(shí)換免費(fèi)中文字體會更省心。樣式問題主要在單位換錯(cuò)。表格里的面積字段如果源數(shù)據(jù)是平方米導(dǎo)出時(shí)要轉(zhuǎn)為公頃或者畝小數(shù)位數(shù)也要統(tǒng)一。這個(gè)可以在布局的表框字段表達(dá)式里做計(jì)算不用改原始數(shù)據(jù)。我的習(xí)慣是單位換算放到字段表達(dá)式里完成這樣同一套工具在不同項(xiàng)目里可以靈活切換單位不會污染源數(shù)據(jù)。5.4 批量出圖效率太慢幾十頁的圖如果每一頁都做實(shí)時(shí)空間查詢耗時(shí)確實(shí)會疊加。三個(gè)優(yōu)化手段。第一個(gè)是簡化表格數(shù)據(jù)源。在出圖專用工程里把表格圖層復(fù)制到內(nèi)存要素類只保留要顯示的字段去掉不必要的關(guān)聯(lián)表、連接操作。內(nèi)存要素類比磁盤數(shù)據(jù)快很多尤其是數(shù)據(jù)量大的面圖層。第二個(gè)是降低導(dǎo)出分辨率。300dpi 是印刷級如果你只做屏幕預(yù)覽或者網(wǎng)頁發(fā)布150dpi 就夠了。導(dǎo)出 PDF 的分辨率直接決定時(shí)間尤其在頁面數(shù)量大的時(shí)候差別非常明顯。第三個(gè)是把“頁面切換”和“導(dǎo)出”拆開。如果出圖工具只在月末或項(xiàng)目交付前跑一次其實(shí)不太需要追求極致速度但如果是天天都要生成的在線圖件建議用 ArcGIS Pro 的“地圖系列批量導(dǎo)出”功能它比用腳本逐頁循環(huán)更快因?yàn)橐鎯?nèi)部做了批量優(yōu)化。腳本循環(huán)的優(yōu)勢在于逐頁控制如果不需要逐頁控制就交給軟件原生的批量導(dǎo)出。問題現(xiàn)象常見原因解決辦法表格不更新?lián)Q頁后表格內(nèi)容不變表框未勾選“僅顯示地圖范圍內(nèi)要素”在表框?qū)傩灾虚_啟空間過濾表格溢出頁面表格超出布局邊界字段太多或行數(shù)過多精簡字段、縮小字號、腳本隱藏表框中文顯示異常導(dǎo)出 PDF 出現(xiàn)方塊字體不支持或未嵌入設(shè)置中文字體、導(dǎo)出時(shí)嵌入字體出圖太慢幾十頁要跑很久實(shí)時(shí)空間查詢開銷大使用內(nèi)存要素類、降低分辨率寫在最后的一點(diǎn)個(gè)人體會這套流程我前前后后給四五個(gè)項(xiàng)目搭過。做分村土地利用圖、做宗地圖、做管線竣工圖表現(xiàn)形式不一樣底層邏輯完全相同地圖系列負(fù)責(zé)切頁表框負(fù)責(zé)空間過濾ArcPy 負(fù)責(zé)批量控制。熟練之后從拿到工程文件到批量出圖跑完也就是改改路徑、調(diào)調(diào)字段的事。如果讓我給剛?cè)脒@行的朋友一個(gè)建議我會說先別急著寫腳本把布局里的一張圖手工配到滿意尤其是表框的字段順序和字號這比任何代碼都重要。我見過太多人代碼寫得很漂亮最后導(dǎo)出的表格要么行高擠成一團(tuán)要么列寬忽寬忽窄反而被業(yè)務(wù)人員打回來反復(fù)改。另外想多說一句動(dòng)態(tài)屬性表這個(gè)需求技術(shù)本身不算難難的是問題描述清楚。如果你去網(wǎng)上搜很容易搜到一堆“怎么把 Excel 表貼到 ArcGIS 布局里”的答案那些都是靜態(tài)方案做完哭都來不及。希望這篇能把“動(dòng)態(tài)”這兩個(gè)字真正說明白讓你少走彎路。