CSV 父子層級範本(產品目錄拆解)
PIM 或 BOM 匯出檔在每一列指名它的父項,所以箭嘴向上指。「連線至」欄指名子項,所以箭嘴向下指。這份範本就是把這次反轉畫出來:五個深度層級、五個判斷、七片葉。
生成呢個圖嘅 CSV 檔
每行一個步驟。「連線至」欄入面嘅數字係行號——就係佢畫出啲連線,亦係大多數檔案缺咗嗰欄。
| # | 形狀 | 方框文字 | 連線至 | 連線文字 | 橫向泳道 | 縱向泳道 |
|---|---|---|---|---|---|---|
| 1 | Start | 戶外生活目錄 | 2, 3 | 根(父欄留空) | 類別紀錄 | |
| 2 | Process | 座椅 | 4 | 深度 1 | 類別紀錄 | |
| 3 | Process | 遮陽與遮蔽 | 7 | 深度 1 | 類別紀錄 | |
| 4 | Decision | 這個類別是否再往下分層? | 5, 6 | 子類別, 可售產品 | 深度 1 | 類別紀錄 |
| 5 | Process | 長椅 | 10 | 深度 2 | 類別紀錄 | |
| 6 | Process | 長椅座墊組 | 8 | 深度 2 | 產品紀錄 | |
| 7 | Process | 懸臂式太陽傘 3 米 | 9 | 深度 2 | 產品紀錄 | |
| 8 | Decision | 這件產品是否有款式? | 11, 12 | 是——一個款式一列, 否——產品那一列就是 SKU | 深度 2 | 產品紀錄 |
| 9 | Decision | 這件零件是否單獨出售? | 13, 14 | 單獨出售, 只供維修 | 深度 2 | 產品紀錄 |
| 10 | Process | 花園長椅 三座位 | 15 | 深度 3 | 產品紀錄 | |
| 11 | Success | 座墊組 原色 | 深度 3 | 款式紀錄 | ||
| 12 | Success | 長椅座墊組 單一 SKU | 深度 3 | 產品紀錄 | ||
| 13 | Success | 替換傘布 3 米 | 深度 3 | 款式紀錄 | ||
| 14 | End | 傘骨組件 | 深度 3 | 元件紀錄 | ||
| 15 | Decision | 是備貨還是按單製造? | 17, 16 | 備貨, 按單製造 | 深度 3 | 產品紀錄 |
| 16 | Decision | 是外購還是自製? | 18, 19 | 外購, 自製 | 深度 3 | 元件紀錄 |
| 17 | Success | 花園長椅 三座位 橡木 | 深度 4 | 款式紀錄 | ||
| 18 | End | 硬木板條組 | 深度 4 | 元件紀錄 | ||
| 19 | End | 鑄鐵長椅框架 | 深度 4 | 元件紀錄 |
#,形狀,方框文字,連線至,連線文字,橫向泳道,縱向泳道
1,Start,戶外生活目錄,"2, 3",,根(父欄留空),類別紀錄
2,Process,座椅,4,,深度 1,類別紀錄
3,Process,遮陽與遮蔽,7,,深度 1,類別紀錄
4,Decision,這個類別是否再往下分層?,"5, 6","子類別, 可售產品",深度 1,類別紀錄
5,Process,長椅,10,,深度 2,類別紀錄
6,Process,長椅座墊組,8,,深度 2,產品紀錄
7,Process,懸臂式太陽傘 3 米,9,,深度 2,產品紀錄
8,Decision,這件產品是否有款式?,"11, 12","是——一個款式一列, 否——產品那一列就是 SKU",深度 2,產品紀錄
9,Decision,這件零件是否單獨出售?,"13, 14","單獨出售, 只供維修",深度 2,產品紀錄
10,Process,花園長椅 三座位,15,,深度 3,產品紀錄
11,Success,座墊組 原色,,,深度 3,款式紀錄
12,Success,長椅座墊組 單一 SKU,,,深度 3,產品紀錄
13,Success,替換傘布 3 米,,,深度 3,款式紀錄
14,End,傘骨組件,,,深度 3,元件紀錄
15,Decision,是備貨還是按單製造?,"17, 16","備貨, 按單製造",深度 3,產品紀錄
16,Decision,是外購還是自製?,"18, 19","外購, 自製",深度 3,元件紀錄
17,Success,花園長椅 三座位 橡木,,,深度 4,款式紀錄
18,End,硬木板條組,,,深度 4,元件紀錄
19,End,鑄鐵長椅框架,,,深度 4,元件紀錄運作方式
找出承載層級的那兩個欄
為了這個目的,匯出檔裡其餘一切都是裝飾。你需要放著每一列自己識別碼的那個欄,以及指名它父項的那個欄。它們很少叫做 id 與 parent_id:去找 parent_sku、belongs_to、category_path 或 assembly。如果父項是一條路徑而不是一個代碼,例如「首頁 > 座椅 > 長椅」,最後一段就是父項,而其餘部分就是深度。如果匯出檔完全沒有父欄卻有一個層級號碼欄,請看下面關於縮排式物料清單的那一則。
把父欄反轉成「連線至」
這就是整件工作。按匯出檔的父欄排序或分組,令每一個父項的子項坐在一起,然後把那些子項的列號寫進父項的「連線至」儲存格,以逗號分隔。方向在這裡掉頭:匯出檔說的是子項指名父項,試算表說的是父項指名子項。有一個後果值得說出聲——父欄是一列一個值,而「連線至」是一列有多少個子項就有多少個值,所以資訊由多列移到了較少的列上。
最後才為列編號,而且要等次序定了才編
「連線至」放的是這一列在表裡的位置,不是它的識別碼,所以 SKU-1042 必須變成承載它那一列的號碼。之後插入一列,插入點以下每一個號碼就差了一。先把列排到最終次序,然後一次過把編號解析成號碼。一個指向不存在的列的「連線至」值,會在畫圖時被無聲丟棄,看起來就像一個純粹忘了連接任何東西的方框。
為「連線至」儲存格加引號,並確認分隔符
「連線至」與「連線文字」放的是以逗號分隔的清單,所以在一個以逗號分隔的檔案裡,那些儲存格必須以雙引號包起——"4,5" 與 "是,否"——否則那一列會多出一個欄位,而它之後的每一個欄都會向左移一格。歐洲的匯出檔經常是以分號分隔的,這令儲存格內部的逗號變得無害,但意味著整個檔案都必須以分號分隔去讀。產品名稱會帶來自己的引號問題:「花園長椅, 三座位」裡的逗號,或者 3" 桿身裡的英寸符號,都要以同樣方式轉義。如果某個欄在匯入時看似被忽略,就檢查第一個標題名稱,因為一個帶位元組順序記號寫成 UTF-8 的檔案,會在它前面帶著三個看不見的位元組。
由這一列是甚麼去設「形狀」,由它坐在哪裡去設「橫向泳道」與「縱向泳道」
有一列拿 Start:父欄留空的那一列。「連線至」留空的列是葉,而一片葉需要一個終止符形狀——End、Success 或 Reject——因為一列非終端而又沒有出向連接線的資料是一條死路。如果對你有幫助,就用這份範本用的分法:客戶可以下單的列用 Success,只在一個組件內部存在的列用 End。然後把你走出來的深度填進「橫向泳道」,把匯出檔自己的類型欄填進「縱向泳道」。一個不被認得的形狀名稱會靜靜地正規化成 Process,所以特別要檢查 Decision 的拼寫。
匯入之前先清掉孤兒、多餘的根與迴路
三項檢查,各有不同的病徵。父欄裡的每一個值都必須在編號欄裡出現過;沒有出現的就是孤兒,通常是因為匯出時篩選到只剩一個類別,而它們的父項住在那之上。應該恰好有一列的父欄留空,如果有幾列都留空,你看的就是幾棵樹。而沒有一列可以經自己的父項回到自己,那種情況會在一次糟糕的合併之後出現,而一旦反轉,它會畫出一條繞回自己的連接線。
常見問題
怎樣把一個父子欄變成流程圖?
先把關係反轉,然後為它編號。匯出檔給你的是子項指名父項;試算表要的是父項指名子項。按父欄把列分組,然後為每一個父項把它子項的列號寫進那個父項的「連線至」儲存格,以逗號分隔。每一列父欄留空的資料都是根,並取 Start 形狀;每一列沒有出現在任何人父欄裡的資料都是葉,「連線至」留空,並取一個終止符形狀。「方框文字」由名稱欄填,「橫向泳道」由你沿父鏈走出來的深度填,「縱向泳道」由匯出檔本來就有的類型欄填。然後把 .csv 拖到編輯器的試算表區域,或者直接把 CSV 文字貼進去。匯入是按標題名稱比對的,所以你檔案裡欄的次序無關緊要,而它不認得的任何欄都會原封帶過並被忽略。
父欄與「連線至」欄有甚麼分別?
方向、基數,以及那個值所指的東西。父欄向上指:每一列指名它上面那唯一一列,所以一列恰好一個值,而葉就是沒有人指名的那些列。「連線至」欄向下指:每一列指名它下面那些列,所以一個有四個子項的父項在一個儲存格裡放四個值,而葉就是儲存格留空的那些列。而那些值在種類上也不同。父欄放的是一個識別碼,例如 SKU-1042 這種無論那一列搬到哪裡都跟著它的東西。「連線至」放的是一個位置,也就是這一列在表裡由 1 起算的號碼,而它會在上面插入一列的那一刻改變。這正是為甚麼識別碼必須在列的次序定下來之後才解析成號碼,而不是之前。
我的欄在檔案中途整批移了位。發生了甚麼事?
幾乎一定是一個沒有加引號的逗號。一個 CSV 列在任何東西看它之前就先按分隔符切開,所以在一個以逗號分隔的檔案裡,一個含有 4,5 的「連線至」儲存格會被讀成兩個欄位,那一列比標題多了一個欄位,而「連線至」之後每一個欄都落在它鄰居的標題底下。把那些儲存格以雙引號包起,解析器就會把它們接回去。「連線文字」同理,因為它也是一份以逗號分隔的清單;含有逗號的產品名稱亦然。如果移位是由最頭那一個欄就開始,成因通常是相反的問題:這個檔案是以分號分隔的——大部分歐洲系統的匯出檔正是如此——卻被當成以逗號分隔去讀;又或者編碼不符,令一個位元組順序記號黏在第一個標題名稱上,於是它再也比對不上。
一列的父項在匯出檔裡找不到會怎樣?
它會變成孤兒,而這是篩選過的匯出檔裡最常見的缺陷。你向系統要一個類別,或者只要有效的物品,而它剛好就把那些列給了你——連同它們的父項編號,而那些編號指向被篩選排除的列。檔案裡沒有任何東西被標示為錯。層級反轉之後,那一列就純粹不會被列進任何人的「連線至」裡,於是它畫出來是一個沒有東西抵達的方框,坐在樹的外面。匯入之前逐列決定它屬於哪一種:一列的父項是被篩選掉的,應該重新掛到最接近的、有被包含進來的祖先之下;而一列的父項在來源系統裡已經不存在的,是一個要退回去修的資料缺陷,而不是一個要畫出來的東西。
如果我的物料清單有一個層級欄而不是父欄,可以用嗎?
可以,而且它會轉換成同一樣東西,只是這次轉換靠的是列的次序而不是列裡的任何一個值。一份縮排式物料清單順著檔案往下重複 1、2、2、3、1 這些層級,而規則是:一列的父項,是它上面最接近、層級剛好低一級的那一列。這意味著匯出檔原本的次序承載著意義——先按料號把檔案排序,層級就沒有了,沒有錯誤,也沒有任何東西可以把它救回來。由上而下走一遍檔案,把每一個層級最後見到的那一列記住,一邊走一邊指派父項,然後才反轉成「連線至」。數量、單位與供應商代碼可以留在它們自己的欄裡,那些欄會通過匯入並被忽略;或者搬進「備註」欄,如果你想它們看得見。