将层次结构从 Excel 列转换为行
Transform hierarchy from Excel columns into rows
我有 Excel 3 列:
OrgunitCode ParentOrgunitCode OrgunitName
1500 Nan Head_Org
3200 1500 2nd_level_Org
3201 1500 other_2nd_lever_Org
..............................................................
971248197 827484 n_level_Org
103048197 513834 n2_level_Org
我需要将其转换为完整的层次结构行(使用 Excel 或 Python):
OrgunitName OrgunitCode OrgunitName(lvl_2) OrgunitCode(lvl_2) .. OrgunitName(lvl_5) OrgunitCode(lvl_5)
Head_Org 1500 2nd_level_Org 3200 n_level_Org 971248197
Head_Org 1500 2nd_level_Org 3200 n2_level_Org 513834
..............................................................
所以我想使用数据透视表,或者在 excel 中查找,但是如果我从 "Parent" 开始搜索,我不知道有多少 "Childrens",所以我很困惑。而且我不知道如何从最低点开始,因为如何找到它们
哦...使用层次结构的乐趣。总是很有趣。
首先,在处理 parent-child 关系时,我总是建议为级别 1 构建像“/”这样的组织节点; '/1/', '/2/' ... '/n/' 用于级别 2; '/1/1', '/2/1/', '/2/2/'... '/n/n/' 用于级别 3 等。这将使您使用层次结构更容易(例如排序、查找不同部门的后代、兄弟姐妹和祖先等)。
在您的情况下,您实际上并不需要组织节点,但我已将其包含在 D 列中以供将来参考:
假设第 1 行是 header 并且数据组织为:
A: OrgunitCode
B: ParentOrgunitCode
C: OrgunitName
然后在第 2 行添加这些公式:
D: OrgNode (not used but useful in future)
=IF(COUNTIFS($A:$A,B2)=0,"/"&A2&"/",VLOOKUP(B2,$A:$D,4,FALSE)&$A2&"/")
E: Hierarchy level
=IF(COUNTIFS($A:$A,$B2)=0,1,VLOOKUP($B2,$A:$E,5,FALSE)+1)
下一个是您要求的层次结构。将此公式分别粘贴到单元格 E2 和 F2 中,然后拖动它们以覆盖所有相关行和层次结构级别。
F: OrgunitName
=IF($E2=(COLUMN()-4)/2,$C2,IF($E2<(COLUMN()-4)/2,"",VLOOKUP($B2,$A:F,COLUMN(),FALSE)))
G: OrgunitCode
=IF($E2=(COLUMN()-5)/2,$A2,IF($E2<(COLUMN()-5)/2,"",VLOOKUP($B2,$A:G,COLUMN(),FALSE)))
请注意,G 和 F 中的查找列是相对的,以避免在向右扩展公式时更改数字或添加数字行以供参考。但是,如果列没有完全按照上面的方式拆分,您可能必须用数字或数字引用替换 'COLUMN()' 部分。
还有一件事:VLOOKUP 在这里起作用,但请注意它对 Excel 来说是一个繁重的操作,所以如果你有一个非常大的层次结构,你可能要考虑使用 [=] 中的层次结构函数43=],MySQL 中的重复函数,或类似的。
公式解析
编辑:按要求对公式进行解释(我认为这是一团糟,但不知道更好的方法):
D: OrgNode (not used but useful in future)
=IF(COUNTIFS($A:$A,B2)=0,"/"&A2&"/",VLOOKUP(B2,$A:$D,4,FALSE)&$A2&"/")
Builds a hierarchy node with the parent/child relationship seperated by '/':
'COUNTIFS($A:$A,B2)=0' <- checks to see if there is a parent.
"/"&A2&"/" <- ...If no, then this is the/a top node, so take the OrgCode and wrap it in '/'
VLOOKUP(B2,$A:$D,4,FALSE)&$A2&"/") <- Else, look up the parent's orgnode and add this department's OrgCode and '/' to the parent's.
E: Hierarchy level
=IF(COUNTIFS($A:$A,$B2)=0,1,VLOOKUP($B2,$A:$E,5,FALSE)+1)
Just determines the hierarchy level of the dept in question.
=IF(COUNTIFS($A:$A,$B2)=0 <- checks to see if there is a parent.
1 <- if not, then make this hierarchy level 1
VLOOKUP($B2,$A:$E,5,FALSE)+1) <- Else, lookup the hierarchy level of the parent and add 1
F: OrgunitName
=IF($E2=(COLUMN()-4)/2,$C2,IF($E2<(COLUMN()-4)/2,"",VLOOKUP($B2,$A:F,COLUMN(),FALSE)))
=IF($E2=(COLUMN()-4)/2, <- checks to see if the current hierarchy column is equal to the hierarchy level of the current department
$C2 <- if so, return the dept name
IF($E2<(COLUMN()-4)/2 <- else check if the current hierarchy column is lower than the hierarchy level of the current department
"" <- if so, remain blank
VLOOKUP($B2,$A:F,COLUMN(),FALSE))) <- else lookup the value in this column of the parent department.
G: OrgunitCode
=IF($E2=(COLUMN()-5)/2,$A2,IF($E2<(COLUMN()-5)/2,"",VLOOKUP($B2,$A:G,COLUMN(),FALSE)))
- Same explanation as above, just a different column reference and returns department code instead
=IF($E2=(COLUMN()-5)/2
$A2
IF($E2<(COLUMN()-5)/2
""
VLOOKUP($B2,$A:G,COLUMN(),FALSE)))
并开辟它:
(COLUMN()-4)/2 <- Instead of hardcoding the hierarhy levels, this uses the column index to calculate the relevant hierarchy level in the given column. Column F is index 6: (6-4)/2 = 1. Column H is index 8: (8-4)/2 = 2. etc.
COLUMN() <- In the VLOOKUP reference: We all know VLOOKUP is annoying beacause we have to manually change the number in the col_index_num parameter when dragging across columns. But similar to above, we can use the column index number as a relative reference. Hence her, column F is index 6 and will look up the 6th column. Column G will return the 7th, H the 8th... you get the point.
我有 Excel 3 列:
OrgunitCode ParentOrgunitCode OrgunitName
1500 Nan Head_Org
3200 1500 2nd_level_Org
3201 1500 other_2nd_lever_Org
..............................................................
971248197 827484 n_level_Org
103048197 513834 n2_level_Org
我需要将其转换为完整的层次结构行(使用 Excel 或 Python):
OrgunitName OrgunitCode OrgunitName(lvl_2) OrgunitCode(lvl_2) .. OrgunitName(lvl_5) OrgunitCode(lvl_5)
Head_Org 1500 2nd_level_Org 3200 n_level_Org 971248197
Head_Org 1500 2nd_level_Org 3200 n2_level_Org 513834
..............................................................
所以我想使用数据透视表,或者在 excel 中查找,但是如果我从 "Parent" 开始搜索,我不知道有多少 "Childrens",所以我很困惑。而且我不知道如何从最低点开始,因为如何找到它们
哦...使用层次结构的乐趣。总是很有趣。
首先,在处理 parent-child 关系时,我总是建议为级别 1 构建像“/”这样的组织节点; '/1/', '/2/' ... '/n/' 用于级别 2; '/1/1', '/2/1/', '/2/2/'... '/n/n/' 用于级别 3 等。这将使您使用层次结构更容易(例如排序、查找不同部门的后代、兄弟姐妹和祖先等)。
在您的情况下,您实际上并不需要组织节点,但我已将其包含在 D 列中以供将来参考:
假设第 1 行是 header 并且数据组织为:
A: OrgunitCode
B: ParentOrgunitCode
C: OrgunitName
然后在第 2 行添加这些公式:
D: OrgNode (not used but useful in future)
=IF(COUNTIFS($A:$A,B2)=0,"/"&A2&"/",VLOOKUP(B2,$A:$D,4,FALSE)&$A2&"/")
E: Hierarchy level
=IF(COUNTIFS($A:$A,$B2)=0,1,VLOOKUP($B2,$A:$E,5,FALSE)+1)
下一个是您要求的层次结构。将此公式分别粘贴到单元格 E2 和 F2 中,然后拖动它们以覆盖所有相关行和层次结构级别。
F: OrgunitName
=IF($E2=(COLUMN()-4)/2,$C2,IF($E2<(COLUMN()-4)/2,"",VLOOKUP($B2,$A:F,COLUMN(),FALSE)))
G: OrgunitCode
=IF($E2=(COLUMN()-5)/2,$A2,IF($E2<(COLUMN()-5)/2,"",VLOOKUP($B2,$A:G,COLUMN(),FALSE)))
请注意,G 和 F 中的查找列是相对的,以避免在向右扩展公式时更改数字或添加数字行以供参考。但是,如果列没有完全按照上面的方式拆分,您可能必须用数字或数字引用替换 'COLUMN()' 部分。
还有一件事:VLOOKUP 在这里起作用,但请注意它对 Excel 来说是一个繁重的操作,所以如果你有一个非常大的层次结构,你可能要考虑使用 [=] 中的层次结构函数43=],MySQL 中的重复函数,或类似的。
公式解析
编辑:按要求对公式进行解释(我认为这是一团糟,但不知道更好的方法):
D: OrgNode (not used but useful in future)
=IF(COUNTIFS($A:$A,B2)=0,"/"&A2&"/",VLOOKUP(B2,$A:$D,4,FALSE)&$A2&"/")
Builds a hierarchy node with the parent/child relationship seperated by '/':
'COUNTIFS($A:$A,B2)=0' <- checks to see if there is a parent.
"/"&A2&"/" <- ...If no, then this is the/a top node, so take the OrgCode and wrap it in '/'
VLOOKUP(B2,$A:$D,4,FALSE)&$A2&"/") <- Else, look up the parent's orgnode and add this department's OrgCode and '/' to the parent's.
E: Hierarchy level
=IF(COUNTIFS($A:$A,$B2)=0,1,VLOOKUP($B2,$A:$E,5,FALSE)+1)
Just determines the hierarchy level of the dept in question.
=IF(COUNTIFS($A:$A,$B2)=0 <- checks to see if there is a parent.
1 <- if not, then make this hierarchy level 1
VLOOKUP($B2,$A:$E,5,FALSE)+1) <- Else, lookup the hierarchy level of the parent and add 1
F: OrgunitName
=IF($E2=(COLUMN()-4)/2,$C2,IF($E2<(COLUMN()-4)/2,"",VLOOKUP($B2,$A:F,COLUMN(),FALSE)))
=IF($E2=(COLUMN()-4)/2, <- checks to see if the current hierarchy column is equal to the hierarchy level of the current department
$C2 <- if so, return the dept name
IF($E2<(COLUMN()-4)/2 <- else check if the current hierarchy column is lower than the hierarchy level of the current department
"" <- if so, remain blank
VLOOKUP($B2,$A:F,COLUMN(),FALSE))) <- else lookup the value in this column of the parent department.
G: OrgunitCode
=IF($E2=(COLUMN()-5)/2,$A2,IF($E2<(COLUMN()-5)/2,"",VLOOKUP($B2,$A:G,COLUMN(),FALSE)))
- Same explanation as above, just a different column reference and returns department code instead
=IF($E2=(COLUMN()-5)/2
$A2
IF($E2<(COLUMN()-5)/2
""
VLOOKUP($B2,$A:G,COLUMN(),FALSE)))
并开辟它:
(COLUMN()-4)/2 <- Instead of hardcoding the hierarhy levels, this uses the column index to calculate the relevant hierarchy level in the given column. Column F is index 6: (6-4)/2 = 1. Column H is index 8: (8-4)/2 = 2. etc.
COLUMN() <- In the VLOOKUP reference: We all know VLOOKUP is annoying beacause we have to manually change the number in the col_index_num parameter when dragging across columns. But similar to above, we can use the column index number as a relative reference. Hence her, column F is index 6 and will look up the 6th column. Column G will return the 7th, H the 8th... you get the point.