布局報(bào)錯(cuò)全解析:從ALV變式到屏幕字段的排查清單)
干 ABAP 的兄弟大概率都撞見過這種事程序編譯都是綠的功能說明書寫得也沒毛病結(jié)果一跑 GUI點(diǎn)個(gè)按鈕或者切個(gè)頁面系統(tǒng)直接彈一個(gè)“屏幕轉(zhuǎn)布局報(bào)錯(cuò)”。第一次見這種提示的人基本都懵因?yàn)樗a邏輯沒直接關(guān)系既不在 Debug 里拋異常也不在你寫的報(bào)表輸出流程里。我前陣子處理一個(gè)客戶問題時(shí)還把整套排查路徑重新走了一遍從請求釋放到布局緩存折騰了大半天才定位到根因。這期就把這類問題的處理思路完整寫出來給同樣被這個(gè)報(bào)錯(cuò)折磨過的人參考。先說清楚這個(gè)標(biāo)題里的“屏幕轉(zhuǎn)布局”并不是某個(gè)標(biāo)準(zhǔn)事務(wù)代碼的官方功能名而是 ABAP 開發(fā)里一類操作場景的統(tǒng)稱當(dāng)你從對話屏幕、選擇屏幕或者 ALV 輸出界面切換到另一種界面布局方式時(shí)系統(tǒng)內(nèi)部做了界面對象和顯示數(shù)據(jù)的重新匹配一旦匹配不上就會冒出一句含義模糊的 Layout 相關(guān)報(bào)錯(cuò)。下面我會把這類報(bào)錯(cuò)拆開講并且附上我自己實(shí)操驗(yàn)證過的排查步驟。1. 報(bào)錯(cuò)到底錯(cuò)在哪一環(huán)先分清三種“屏幕轉(zhuǎn)布局”處理這種報(bào)錯(cuò)最忌諱的就是上來就翻代碼因?yàn)槟銓?bào)錯(cuò)場景的定義如果錯(cuò)了后面所有排查都是白費(fèi)時(shí)間。根據(jù)我在項(xiàng)目上的經(jīng)驗(yàn)所謂“屏幕轉(zhuǎn)布局報(bào)錯(cuò)”至少能分成三類每類的處理路徑完全不同。第一類是 ALV 輸出布局相關(guān)。這種情況最多通常出現(xiàn)在報(bào)表執(zhí)行完、用戶想保存或者切換 ALV Grid 顯示變式時(shí)系統(tǒng)提示 Layout 不存在、Layout 無法加載或者保存布局時(shí)報(bào)錯(cuò)。這類問題本質(zhì)上是變式管理的鍋跟你在 GUI 狀態(tài)欄里設(shè)置的列寬、排序、篩選條件可能有關(guān)也可能跟你代碼里傳給 ALV 的變式名不匹配有關(guān)。第二類是 Dynpro 屏幕元素布局相關(guān)。你維護(hù)了一個(gè)對話程序或者函數(shù)組子屏幕里面放了幾十個(gè) I/O 字段然后你在 Screen Painter 里把字段拖拽調(diào)整了位置或者把某個(gè)字段的模塊化屬性改掉再激活屏幕時(shí)系統(tǒng)告訴你布局轉(zhuǎn)換不一致。這種情況本質(zhì)上是屏幕字段定義和 ABAP 程序里的字段目錄沒對齊。第三類是界面上做聯(lián)動跳轉(zhuǎn)時(shí)的布局轉(zhuǎn)換報(bào)錯(cuò)。比如你在某個(gè)報(bào)表里點(diǎn)了“轉(zhuǎn)到”按鈕跳到一個(gè)事務(wù)代碼或者另一個(gè) ALV 界面跳轉(zhuǎn)過去后新界面嘗試沿用舊界面的布局參數(shù)結(jié)果兩個(gè)界面字段目錄差別太大系統(tǒng)轉(zhuǎn)換不過來直接報(bào)錯(cuò)。這里建議所有初學(xué)者先做一個(gè)動作把報(bào)錯(cuò)彈窗完整截圖尤其注意報(bào)錯(cuò)消息號。ABAP 里的報(bào)錯(cuò)消息大多有規(guī)律消息類加上三位數(shù)字基本能鎖定問題域。如果是類式消息比如MESSAGE E003(ZMSG)這種去 SE91 查一下消息文本往往能得到比彈窗上更具體的描述。如果消息號是空的或者顯示的是運(yùn)行時(shí)異常那大概率不是標(biāo)準(zhǔn)消息類得靠 Debug 或者看系統(tǒng)日志。2. 從典型報(bào)錯(cuò)文本反推原因報(bào)錯(cuò)文本是排查的第一道線索但很多 ABAP 開發(fā)者看到英文報(bào)錯(cuò)就頭大。其實(shí)不用整段讀懂抓關(guān)鍵結(jié)構(gòu)就行。我見過最多的幾類提示包括Layout 后面帶一串變式名然后提示 does not existFunction module...was not called / terminatedField catalog differs from layoutInternal error in screen conversionError when generating screen / Layout not generated這幾類話術(shù)指向的地方完全不一樣。凡是帶變式名的比如Layout ZTEST_VAR does not exist問題十有八九出在 ALV 變式讀取上。你代碼里調(diào)用 ALV 時(shí)指定了一個(gè)用戶默認(rèn)變式但這個(gè)變式在系統(tǒng)里根本沒被保存過或者因?yàn)檎埱鬀]釋放、被傳輸?shù)搅肆硪粋€(gè)系統(tǒng)但沒激活都會出現(xiàn)這種“系統(tǒng)找不到東西”的提示。凡是帶 Function module terminated 的通常是你在轉(zhuǎn)換布局時(shí)調(diào)用了標(biāo)準(zhǔn)函數(shù)模塊比如REUSE_ALV_GRID_DISPLAY或LVC_VARIANT_LOAD而這些模塊在內(nèi)部執(zhí)行時(shí)觸發(fā)了錯(cuò)誤。這種時(shí)候光看外層信息沒用得點(diǎn)進(jìn)去看內(nèi)部異?;蛘咧苯哟騻€(gè) Debug 斷點(diǎn)看它到底是哪一行炸的。凡是帶 Field catalog differs 的說明你傳給 ALV 或者屏幕的字段目錄和你實(shí)際數(shù)據(jù)顯示結(jié)構(gòu)不一致。比如你把內(nèi)表的字段從MATNR改成WERKS但 Fieldcat 里還掛著舊字段結(jié)果一轉(zhuǎn)換布局系統(tǒng)拿著舊字段去匹配新數(shù)據(jù)自然報(bào)錯(cuò)。這種問題在代碼調(diào)整后特別常見因?yàn)槲乙娺^不少開發(fā)者在復(fù)制粘貼代碼時(shí)把字段目錄漏改了。最后一種帶 generated 的集中在 Screen Painter 場景。屏幕布局文件是激活時(shí)生成的如果激活過程被中斷或者有舊對象鎖著布局文件就生成不出來運(yùn)行時(shí)報(bào)錯(cuò)也就順理成章了。報(bào)錯(cuò)文本關(guān)鍵詞問題方向優(yōu)先排查點(diǎn)Layout ... does not existALV變式讀取變式保存、權(quán)限、請求狀態(tài)Function module terminatedALV內(nèi)部調(diào)用Debug內(nèi)部異常、參數(shù)合法性Field catalog differs字段目錄不一致內(nèi)表結(jié)構(gòu)、Fieldcat定義Error when generating screenDynpro布局生成激活狀態(tài)、對象鎖、請求Internal error in screen conversion多界面布局聯(lián)動跳轉(zhuǎn)參數(shù)、屏幕字段統(tǒng)一3. 實(shí)戰(zhàn)拆解一次改屏幕字段引發(fā)的連鎖報(bào)錯(cuò)為了把這個(gè)話題講透我用一個(gè)最近實(shí)際處理過的例子來串一遍完整排查過程??蛻魣鼍笆?MD07 庫存需求清單的增強(qiáng)報(bào)表開發(fā)人員修改了報(bào)表輸出部分加了兩個(gè)顯示列然后順手在輸出 TYPE 和是否顯示之間做了聯(lián)動。改完后開發(fā)自測執(zhí)行報(bào)表沒任何問題但只要用戶對 ALV 表格做一次變式保存或者點(diǎn)擊“切換布局”系統(tǒng)就會彈出文章標(biāo)題里這類報(bào)錯(cuò)。這個(gè)項(xiàng)目里的問題卡了很久因?yàn)殚_發(fā)本地測試是好的。后來我遠(yuǎn)程看了下還原步驟發(fā)現(xiàn)報(bào)錯(cuò)只在用戶保存新布局時(shí)才出現(xiàn)而且不是所有用戶都復(fù)現(xiàn)。這里基本可以判斷問題不在 ALV 輸出邏輯本身而在變式管理層面。接著我在代碼里搜布局相關(guān)調(diào)用很快發(fā)現(xiàn)問題。程序使用的是老式 ALV 函數(shù)模塊REUSE_ALV_GRID_DISPLAY參數(shù)里傳入了一個(gè)IS_VARIANT指定變式名為空同時(shí)設(shè)了I_SAVE U。按標(biāo)準(zhǔn)行為這個(gè)配置允許每個(gè)用戶保存自己的布局作為用戶特定變式系統(tǒng)會自動生成變式名稱通常是Report名加上用戶ID的某種組合。理論上沒毛病但問題出在這個(gè)報(bào)表的變式命名規(guī)則和程序里的一個(gè)自定義沖突判斷邏輯上。開發(fā)人員在這個(gè)程序里加了一段代碼在輸出前會去讀系統(tǒng)里已有的變式列表然后根據(jù)列表里是否存在某個(gè)命名格式來判斷是否需要初始化輸出格式。這個(gè)邏輯本身很聰明但它用的是老式的RS_VARIANT_CONTENTS方法來讀變式存儲而這個(gè)函數(shù)對新格式的持久化布局讀取并不完全兼容。結(jié)果就是標(biāo)準(zhǔn) ALV 顯示時(shí)能正常讀取變式但開發(fā)人員自定義的這段邏輯讀不到返回空值然后程序走了錯(cuò)誤分支誤認(rèn)為布局不存在隨即拋錯(cuò)。修復(fù)方案并不復(fù)雜。我們把自定義讀取變式的邏輯改成直接調(diào)用 ALV 輸出前標(biāo)準(zhǔn)會用的那套變式讀取機(jī)制也就是檢查LVC_VARIANT_DEFAULT_GET獲取默認(rèn)布局再配合LVC_VARIANT_LOAD做加載。如果默認(rèn)布局不存在就跳過自定義判斷不阻塞標(biāo)準(zhǔn)保存邏輯。這個(gè)案例給一個(gè)很重要的啟發(fā)在做 ABAP 增強(qiáng)時(shí)能不動標(biāo)準(zhǔn)變式邏輯就盡量別去動尤其是自己拼變式名去讀取和判斷的這種操作很容易埋雷。因?yàn)?ALV 布局變式在不同版本上的存儲機(jī)制有差異有些老方法是“碰巧能用”不等于所有場景都能用。3.1 標(biāo)準(zhǔn) ALV 布局調(diào)用點(diǎn)檢查清單如果你的代碼里用到了 ALV建議按下面順序自查一遍。先看I_SAVE參數(shù)它決定了布局能否被保存。X表示保存通用變式和用戶特定變式U表示只保存用戶特定變式表示不允許保存。很多項(xiàng)目的自定義 ALV 報(bào)表直接沒傳I_SAVE導(dǎo)致用戶無法保存布局但報(bào)錯(cuò)文案不是“沒有保存按鈕”而是“布局不存在”容易誤導(dǎo)排查方向。然后看IS_VARIANT-VARIANT字段。如果你固定傳了一個(gè)值那么這個(gè)變式必須在系統(tǒng)里已存在否則用戶在沒有該變式的系統(tǒng)上運(yùn)行就會直接報(bào)錯(cuò)。這也是項(xiàng)目里最常出現(xiàn)的一個(gè)低級錯(cuò)誤開發(fā)環(huán)境保存了變式傳輸?shù)綔y試環(huán)境忘了傳結(jié)果測試人員一跑就報(bào)了“Layout does not exist”。你以為是代碼問題其實(shí)是測試環(huán)境缺對象。最后看 Fieldcat 是否顯式指定了NO_OUT、COL_POS、TECH這些字段。我曾經(jīng)遇到過一種報(bào)錯(cuò)就是 Fieldcat 里有同一個(gè)字段名被定義了兩次一次是輸出一次是技術(shù)字段結(jié)果 ALV 在布局轉(zhuǎn)換時(shí)不知道該拿哪條記錄去做匹配內(nèi)部拋了一個(gè)非常抽象的異常。這種情況你把 Fieldcat 構(gòu)建邏輯里重復(fù)字段名清理掉就自然恢復(fù)。3.2 代碼改完后為什么還在報(bào)錯(cuò)代碼檢查完還有一多半問題出在激活和傳輸環(huán)節(jié)。ABAP 里屏幕和布局都是激活對象如果你在 SE80 改了屏幕屬性比如把一個(gè)字段從輸入狀態(tài)改成輸出狀態(tài)或者調(diào)整了表格控件屬性必須保證屏幕已經(jīng)成功激活。很多時(shí)候你在修改后沒有完全激活保存了原件但當(dāng)前生成版本還是舊的運(yùn)行時(shí)就報(bào)錯(cuò)。這種問題最直接的驗(yàn)證方法是到 SE80 里找到對應(yīng)屏幕右鍵選擇“激活”看是否報(bào)語法錯(cuò)誤。除了激活狀態(tài)還要看對象是否被鎖。如果某個(gè)開發(fā)同事的會話里還開著同一函數(shù)組并且處于編輯狀態(tài)屏幕上顯示的布局對象會被加鎖這時(shí)你喚醒自己的傳輸請求也沒用必須讓對方釋放編輯模式。項(xiàng)目上經(jīng)常出現(xiàn)“屏布局錯(cuò)誤”其實(shí)是多人同時(shí)改一個(gè)屏幕鬧出來的鎖沖突。4. 代碼里的調(diào)試點(diǎn)從報(bào)錯(cuò)位置回到數(shù)據(jù)流如果前面兩層排查都沒找到問題那就必須上 Debugger 了別怕浪費(fèi)時(shí)間。像我上面說的很多“屏幕轉(zhuǎn)布局”類報(bào)錯(cuò)的真實(shí)異常點(diǎn)藏在 ABAP 標(biāo)準(zhǔn)函數(shù)或者方法內(nèi)部直接看堆棧能省很多事。先明確一個(gè)問題你想在這個(gè)事務(wù)里看到的報(bào)錯(cuò)是前端彈出來的還是后臺拋出的如果是后臺 Job 里出現(xiàn)這種錯(cuò)誤那大概率是程序在無人值守模式下嘗試調(diào)用了需要 GUI 交互的 ALV 布局操作系統(tǒng)根本無法彈出界面于是在后臺處理中報(bào)了“screen cannot be displayed”的錯(cuò)。這種情況不是布局真有問題是調(diào)用邏輯沒做有無 GUI 的判斷。你需要在調(diào)用前檢查CL_GUI_FRONTEND_SERVICESHAS_GUI或者類似的前端可用性判斷。如果返回值是空就走一條不依賴 GUI 的輸出分支問題自然消失。如果報(bào)錯(cuò)是前臺彈的那第一步要抓的是報(bào)錯(cuò)點(diǎn)位置。點(diǎn)開報(bào)錯(cuò)彈窗上的“技術(shù)信息”按鈕或者用/N命令進(jìn)到當(dāng)前 session 的 ABAP 調(diào)試。很多情況下你根本不用設(shè)斷點(diǎn)在報(bào)錯(cuò)現(xiàn)場按SHIFTF3觸發(fā)調(diào)試系統(tǒng)會帶你到異常拋出的那一行你直接看調(diào)用棧往回退就能找到是哪個(gè)自開發(fā)程序調(diào)用了出錯(cuò)的函數(shù)。這里有個(gè)實(shí)用技巧把報(bào)錯(cuò)發(fā)生時(shí)的所有全局變量尤其是變式名、用戶名、程序名、屏幕號全部記下來。比如 ALV 報(bào)錯(cuò)時(shí)GS_VARIANT-VARIANT是什么值SY-UNAME是誰SY-CPROG當(dāng)前是哪個(gè)程序。這些東西組合在一起基本能判斷是“這個(gè)用戶沒有這個(gè)變式”還是“這個(gè)程序壓根沒傳變式”。我有一次就是靠這三個(gè)變量鎖定問題的報(bào)錯(cuò)用戶在測試環(huán)境有一個(gè)跨客戶端通用的變式而這個(gè)變式只在開發(fā)客戶端被保存和傳輸別的客戶端完全沒有所以只有他一跑就炸。4.1 Debug 時(shí)重點(diǎn)看的三個(gè)點(diǎn)第一SY-SUBRC的值。在調(diào)用標(biāo)準(zhǔn)函數(shù)后別急著往下執(zhí)行先看返回值很多開發(fā)者習(xí)慣性忽略返回值等布局報(bào)錯(cuò)時(shí)已經(jīng)不知道是第幾個(gè)函數(shù)出的問題。第二調(diào)用 ALV 之前的內(nèi)表內(nèi)容。布局轉(zhuǎn)換錯(cuò)誤很多時(shí)候不是布局文件的錯(cuò)而是你輸出的數(shù)據(jù)內(nèi)容里包含了無法映射的字段值。比如某個(gè)字段的域值沒有維護(hù)對應(yīng)文本或者數(shù)據(jù)行里出現(xiàn)了空白行導(dǎo)致輸出時(shí)轉(zhuǎn)換布局觸發(fā)異常。這種情況你需要看內(nèi)表最后一行的內(nèi)容特別是金額、數(shù)量的類型是否匹配以及有沒有突然冒出來的初始行。第三Fieldcat 的行數(shù)。把GT_FIELDCAT的行數(shù)打印出來對齊內(nèi)表結(jié)構(gòu)看字段順序是不是錯(cuò)位了。我記得有一次客戶表單整個(gè)數(shù)據(jù)全部左移了一列結(jié)果布局轉(zhuǎn)換時(shí)系統(tǒng)拿第一列的數(shù)據(jù)去匹配最后一列的字段屬性自然全部報(bào)錯(cuò)。這種問題往往是你在構(gòu)建 Fieldcat 時(shí)漏了CLEAR導(dǎo)致上一次循環(huán)的數(shù)據(jù)殘留。4.2 偶發(fā)性報(bào)錯(cuò)先查緩存刷新如果報(bào)錯(cuò)不是每次都發(fā)生而是“時(shí)好時(shí)壞”那首先懷疑的不是代碼而是緩存。SAP GUI 本地的布局緩存、ABAP 服務(wù)器端的屏幕緩沖區(qū)、甚至是前端機(jī)器上的臨時(shí)文件都可能造成偶發(fā)性的布局錯(cuò)亂。最省時(shí)間的操作是讓用戶退出當(dāng)前 SAP GUI然后重新登錄。如果換個(gè)客戶端后不報(bào)錯(cuò)大概率是這臺機(jī)器上的本地緩存文件壞了。找到 SAP GUI 安裝目錄下的緩存路徑刪掉再重登或者直接換個(gè)干凈的目錄重裝一次客戶端。服務(wù)器端的解法是用事務(wù)代碼SE03里相關(guān)工具清理屏幕緩沖區(qū)。注意操作之前看下系統(tǒng)里有沒有其他開發(fā)在干活緩沖區(qū)的全局清理會影響在線用戶最好在業(yè)務(wù)低峰期做。如果不是緊急生產(chǎn)問題建議先讓用戶停手等一個(gè)可以操作的時(shí)間窗口再處理。5. 這類問題最容易隱藏的三個(gè)坑前幾節(jié)講的是怎么修這節(jié)分享三個(gè)我在項(xiàng)目里反復(fù)踩過、而且常規(guī)查錯(cuò)方式基本發(fā)現(xiàn)不了的坑。建議收藏下次遇到“屏幕轉(zhuǎn)布局報(bào)錯(cuò)”先對照一遍。5.1 變式和請求的“半傳輸”狀態(tài)SAP 開發(fā)里有一個(gè)很隱蔽的現(xiàn)象代碼對象傳輸?shù)搅四繕?biāo)系統(tǒng)但變式內(nèi)容并沒有完整跟隨傳輸或者只傳了一半。這會導(dǎo)致在源系統(tǒng)里一切都好目標(biāo)系統(tǒng)里報(bào) Layout 不存在的錯(cuò)。為什么會出現(xiàn)半傳輸因?yàn)樽兪酱鎯τ袃煞N普通變式存在表里ALV 專用的布局變式可能跟報(bào)表程序綁定傳輸時(shí)如果你的傳輸請求里只包含主程序而不包含相關(guān)變式數(shù)據(jù)目標(biāo)系統(tǒng)就等于“有程序但沒布局”。排查技巧是到目標(biāo)系統(tǒng) SE01 看請求狀態(tài)如果請求已經(jīng)釋放但顯示“部分對象激活失敗”十有八九就是這種狀態(tài)。建議處理方式不是手動去目標(biāo)系統(tǒng)創(chuàng)建一個(gè)相同的變式那治標(biāo)不治本。你需要在源系統(tǒng)把變式導(dǎo)出為獨(dú)立的傳輸請求重新傳輸一遍確保目標(biāo)系統(tǒng)里看到的對象狀態(tài)和源系統(tǒng)一致。5.2 權(quán)限對象擋住了布局讀取另一種情況是用戶能執(zhí)行報(bào)表但保存布局或者讀取已有布局時(shí)報(bào)錯(cuò)。這不是字段權(quán)限也不是程序權(quán)限而是變式權(quán)限。ABAP 的變式讀取受權(quán)限對象S_VARIANT控制。如果用戶權(quán)限里沒有這個(gè)對象系統(tǒng)雖然在界面上顯示變式按鈕但一點(diǎn)就報(bào)錯(cuò)且報(bào)錯(cuò)文案往往是通用性的“布局錯(cuò)誤”不會提示你權(quán)限不足。排查方法很簡單讓一個(gè)能夠正常使用的用戶比如 SAP_ALL 用戶去同樣的報(bào)表測試一下。如果 SAP_ALL 用戶沒問題而普通業(yè)務(wù)賬號復(fù)現(xiàn)基本能確認(rèn)是權(quán)限對象缺失。去 PFCG 角色里補(bǔ)上S_VARIANT對應(yīng)權(quán)限并把變式名范圍設(shè)成*測試后再收斂范圍。這個(gè)坑很坑人因?yàn)樗憩F(xiàn)得跟技術(shù)問題一模一樣。5.3 傳輸后忘記激活第三種是最低級的錯(cuò)誤但也最常見。測試機(jī)或者生產(chǎn)機(jī)上收到了請求傳輸狀態(tài)顯示成功所有人松了一口氣結(jié)果第二天運(yùn)行報(bào)錯(cuò)。一查對象到了但是沒激活或者激活時(shí)報(bào)了依賴對象的警告只激活了一半。ABAP 的對象要求所有相關(guān)組件同時(shí)處于激活狀態(tài)屏幕布局轉(zhuǎn)換涉及屏幕、程序、函數(shù)組等多個(gè)對象任何一個(gè)沒激活運(yùn)行時(shí)就可能炸。所以我的習(xí)慣是每次代碼傳入新環(huán)境后第一時(shí)間用 SE80 打開相關(guān)程序把程序、屏幕、函數(shù)組、模塊池全部選中統(tǒng)一激活一遍。再懶也至少執(zhí)行一次SE30里的激活所有未激活對象檢查。這一步不光為你省后續(xù)排查時(shí)間也避免用戶一登錄就撞上“屏幕轉(zhuǎn)布局報(bào)錯(cuò)”這種勸退級提示。6. 從報(bào)錯(cuò)到預(yù)防改版前先把布局邏輯固化進(jìn)開發(fā)規(guī)范處理完眼前的報(bào)錯(cuò)如果項(xiàng)目里相關(guān)功能還很多我建議從機(jī)制上做一輪收斂減少后續(xù)同類問題出現(xiàn)。這里分享幾個(gè)我在團(tuán)隊(duì)內(nèi)部推過的做法。第一凡是新建的 ALV 報(bào)表統(tǒng)一優(yōu)先使用面向?qū)ο蟮?SALV 類而不是老式函數(shù)模塊。SALV 對布局的處理封裝得更完整變式的保存和讀取不需要自己拼參數(shù)出錯(cuò)概率明顯低于 REUSE_ALV。如果用老式函數(shù)模塊代碼評審時(shí)就要檢查I_SAVE和IS_VARIANT是否都傳入且有意義。第二不要在 ALV 輸出前搞變式預(yù)讀和自定義判斷邏輯。像我在第三節(jié)提到的案例開發(fā)人員想判斷“用戶上次用了哪個(gè)布局”來調(diào)整輸出格式這種需求出發(fā)點(diǎn)是好的但它增加了中間環(huán)節(jié)。標(biāo)準(zhǔn)的做法是先讓 ALV 自己讀取和套用變式輸出完成后如果需要知道當(dāng)前生效的布局可以通過 ALV 提供的事件或者方法回讀而不是搶在 ALV 前自行判斷。第三屏幕字段調(diào)整要成對進(jìn)行。任何時(shí)候改了一個(gè)屏幕字段的顯示屬性記得同時(shí)檢查對應(yīng) ABAP 程序里的字段目錄定義、內(nèi)表工作區(qū)字段以及選擇屏幕對應(yīng)的數(shù)據(jù)庫字段屬性。我項(xiàng)目上有一條不成文的規(guī)矩屏幕和 layout 相關(guān)對象不做碎片化修改要么一次性完整改完并伴隨激活要么不做。因?yàn)槠聊晦D(zhuǎn)布局報(bào)錯(cuò)很大一部分來自字段屬性在不同對象間的不一致。第四布局變式的命名必須有規(guī)則。至少在項(xiàng)目里指定前綴比如ZMM_01_VAR這類格式。不要出現(xiàn)張三建了一個(gè)TEST1李四建了一個(gè)TEST1然后系統(tǒng)里同名變式互相覆蓋的情況。命名規(guī)則的意義不只是方便管理更防止傳輸時(shí)不同變式名稱沖突導(dǎo)致目標(biāo)系統(tǒng)里讀到錯(cuò)誤的布局?jǐn)?shù)據(jù)。這幾個(gè)規(guī)范看起來簡單但真能減少那種讓用戶和 ABAP 開發(fā)一起崩潰的“玄學(xué)報(bào)錯(cuò)”。我在幾個(gè)長期維護(hù)的項(xiàng)目里推行過半年后再去看問題清單Layout 相關(guān)報(bào)錯(cuò)的數(shù)量下降非常明顯。7. 附加場景F.19、MD07 這類標(biāo)準(zhǔn)事務(wù)也報(bào)布局錯(cuò)時(shí)有兄弟可能會問自己沒寫多復(fù)雜代碼就是跑個(gè)標(biāo)準(zhǔn)事務(wù)比如 F.19 期末結(jié)算報(bào)表或者 MD07 物料需求清單怎么也會彈這種布局錯(cuò)誤。標(biāo)準(zhǔn)功能報(bào)這類錯(cuò)通常不是你的配置錯(cuò)了而是系統(tǒng)數(shù)據(jù)層面有臟數(shù)據(jù)或者同一個(gè)功能被第二層增強(qiáng)邏輯干擾了。F.19 出現(xiàn)布局報(bào)錯(cuò)時(shí)多半和輸出格式的變式有關(guān)。F.19 大量使用了列表輸出和 ALV 變式來展示結(jié)算差異如果上一財(cái)年產(chǎn)生的報(bào)表變式在配置里沒清理干凈當(dāng)前年度運(yùn)行時(shí)就可能引用到失效的布局。排查方式去 SE36 或者相關(guān)變式事務(wù)里找跟 F.19 相關(guān)的變式組把過期的變式清一遍。如果客戶堅(jiān)持要保留歷史變式那至少要在變式描述上標(biāo)注年度避免當(dāng)前年誤讀到上一年的列布局。MD07 的布局錯(cuò)更容易讓人誤解。它本身是一個(gè)集合了庫存、需求、收貨等多個(gè)來源數(shù)據(jù)的匯總報(bào)表輸出字段在不同的視圖之間切換時(shí)如果內(nèi)部關(guān)聯(lián)的字段目錄沒有同步更新就會出現(xiàn)“屏幕轉(zhuǎn)布局報(bào)錯(cuò)”。這時(shí)候不要想著去改 MD07 的標(biāo)準(zhǔn)代碼先看一下項(xiàng)目里有沒有做 MD07 的隱式增強(qiáng)。很多 MD07 相關(guān)問題都是增強(qiáng)代碼里拼接了額外字段破壞了原有標(biāo)準(zhǔn)布局。還有一個(gè)容易被忽略的場景是 SAP HANA SLT 配置完之后因?yàn)榈讓訑?shù)據(jù)庫結(jié)構(gòu)變化某些老 ABAP 報(bào)表對字段類型的判斷出現(xiàn)偏差特別是日期和時(shí)間字段在布局轉(zhuǎn)換時(shí)類型映射失敗。遇到這種問題優(yōu)先看數(shù)據(jù)庫表字段在 HANA 里是否被自動轉(zhuǎn)換成了新類型然后調(diào)整 ABAP 端的類型聲明以匹配實(shí)際存儲類型。如果你們項(xiàng)目用了 IDOC 做物料主數(shù)據(jù)同步每次創(chuàng)建或修改物料時(shí)外圍系統(tǒng)都在等 IDOC這時(shí)外圍系統(tǒng)報(bào)錯(cuò)說數(shù)據(jù)接收失敗不要只查 PI 層?;仡^看一眼同步程序的輸出結(jié)構(gòu)當(dāng) ABAP 端新增了屏幕字段但沒同步到 IDOC SegmentIDOC 收到的數(shù)據(jù)結(jié)構(gòu)和外部系統(tǒng)期望不一致外部系統(tǒng)就會拒絕接收嚴(yán)格來說這也是一種“布局轉(zhuǎn)換”不匹配。物料憑證的場景也類似BAPI 調(diào)用后如果返回的消息里含M7 000之類的提示先看自定義增強(qiáng)有沒有往 BAPI 結(jié)構(gòu)里塞多余字段。這些非典型的場景看起來分散背后邏輯是一致的一切界面布局、輸出結(jié)構(gòu)、數(shù)據(jù)同步本質(zhì)上都是字段集合的轉(zhuǎn)換。轉(zhuǎn)換兩邊字段對不上系統(tǒng)就拿一個(gè)模糊的報(bào)錯(cuò)來結(jié)束你的操作。當(dāng)你理解了這個(gè)共性以后遇到任何布局報(bào)錯(cuò)都不會慌按著字段匹配的規(guī)則去查比在網(wǎng)絡(luò)上亂搜報(bào)錯(cuò)文本要有用得多。