如何对两个 Excel 表实现各种类型的 JOIN

Excel中的sheet分为3类,其中sheet A是基础表,部分数据如下:


A B C
1 interval1 interval2 interval3
2 1 hour 1 day 1 week
3 2 hours 2 days 2 weeks
4 3 hours 3 days 3 weeks
5 4 hours 4 days 4 weeks

Sheet B1\B2…Bn是关联表,它们的格式都一样,且与A有相同的列interval1interval2interval3。其中一个B的部分数据如下:


A B C D E F G
1 interval1 interval2 interval3 Type value1 value2 value3
2 2 hours 1 day 7 week circle 37 108.1 4.1
3 3 hours 3 days 7 weeks Line 39 117.5 4.2
4 4 hours 4 days 7 weeks Line 35 127 4.3

Sheet C用来描述AB1\B2..BnJoin类型,共3种,其中cross Join表示笛卡尔积;leftJoinBig表示左关联,关联列是interval1leftJoinSmall也是左关联,关联列是interval1interval2。部分数据如下:


A B
1 table joinType
2 B1 crossJoin
3 B2 leftJoinBig
4 B3 leftJoinSmall

计算目标:按照sheet C中的join类型将sheet AB1\B2..Bn关联起来,从A中取interva1列,从B取其他列,最后形成nExcel文件。

以上面的sheet B为例(实际上每个B应当不同),如果joinType==crossJoin,则关联结果应该是:


A B C D E F G
1 interval1 interval2 interval3 Type value1 value2 value3
2 1 hour 1 day 7 week Circle 37 108.1 4.1
3 1 hour 3 days 7 weeks Line 39 117.5 4.2
4 1 hour 4 days 7 weeks Line 35 127 4.3
5 2 hours 1 day 7 week circle 37 108.1 4.1
6 2 hours 3 days 7 weeks Line 39 117.5 4.2
7 2 hours 4 days 7 weeks Line 35 127 4.3
8 3 hours 1 day 7 week circle 37 108.1 4.1
9 3 hours 3 days 7 weeks Line 39 117.5 4.2
10 3 hours 4 days 7 weeks Line 35 127 4.3
11 4 hours 1 day 7 week circle 37 108.1 4.1
12 4 hours 3 days 7 weeks Line 39 117.5 4.2
13 4 hours 4 days 7 weeks Line 35 127 4.3

如果joinType==leftJoinBig,则关联结果应该是:


A B C D E F G
1 interval1 interval2 interval3 Type value1 value2 value3
2 1 hour
3 2 hours 1 day 7 week circle 37 108.1 4.1
4 3 hours 3 days 7 weeks line 39 117.5 4.2
5 4 hours 4 days 7 weeks line 35 127 4.3

如果joinType==leftJoinSmall,则关联结果应该是:


A B C D E F G
1 interval1 interval2 interval3 type value1 value2 value3
2 1 hour
3 2 hours
4 3 hours 3 days 7 weeks line 39 117.5 4.2
5 4 hours 4 days 7 weeks line 35 127 4.3

这个计算需要循环遍历sheet C,因此只能用脚本而不是公式来实现。Join属于结构化计算,VBA缺乏直接可用的函数,代码会非常繁琐。

实现步骤:

1.      运行集算器(可以到润乾官网下载,用职场版,首次运行时会提示加载授权,下载个免费的就够了)

2.  编写脚本并执行


A B
1 =file("data.xlsx").xlsopen()
2 =A1.xlsimport@t(;"C")
3 =tableA=A1.xlsimport@t(;"A")
4 for A2 =tableB=A1.xlsimport@t(;A4.table)
5
=case(A4.joinType,
  "crossJoin",xjoin(tableA:A;tableB:B),
  "leftJoinBig",xjoin@1 (tableA:A;tableB:B,A.interval1==interval1),
  "leftJoinSmall",xjoin@1(tableA:A;tableB:B,A.interval1==interval1   && A.interval2==interval2))
6
=B5.new(A.interval1,B.interval2,B.interval3,B.type,B.value1,B.value2,B.value3)
7
=file(A4.table+A4.joinType+".xlsx").xlsexport@t(B6)

脚本函数 case 可对 Join 类型做分支判断,xjoin 算出笛卡尔积,@1 表示左关联。