Ms access Access中VBA代码的改进,以实现类似透视表的功能
我在MS Access 2007中有一个数据表。每个记录有6个字段,数千条记录。我想制作一种类似透视表的对象。也就是说,如果前4个字段中的任意两行恰好相同,那么它们最终将分组到一行中。此透视表中的列标题将是第5个字段中的值,透视表中的值将是第6个字段,即美元金额。将第5个字段想象为字母A、B、C、D、E、F、G。因此,我开始的表格可能有一行,第5个字段中有A,第6个字段中有3.48美元。另一行可能在前4个字段中匹配,第5个字段中有B,第6个字段中有8.59美元。另一个可能在前4个字段匹配,第5个字段为E,第6个字段为45.20美元。我希望将所有这些行转换为一行(在新表中),从它们匹配的前4个字段开始,然后列出$3.48、$8.59、$0.00、$0.00、$45.20、$0.00、$0.00,对应于列标题a、B、C、D、E、F、G(因为没有包含C、D、F、G的记录,它们对应的值是$0.00),然后以另一个字段结束,该字段合计该行的金额 目前,我有一些VBA代码可以做到这一点,是几年前由其他人编写的。这是非常缓慢,我希望有一个更好的方式。我问了以前的一个问题(但不是很清楚,所以有人建议我创建一个新问题),我在问是否有更好的方法在VBA中实现这一点。我的问题是关于通过VBA在Access中一次读取和写入大量数据,我知道这是Excel中的一个很好的做法。也就是说,我希望获得我的原始表,然后一次将整个内容分配给一个数组(在Excel中,而不是一个单元格一个单元格),然后在VBA中使用该数组并创建一些新数组,然后将整个数组一次写入一个新表(而不是逐个记录,逐个字段)。从这个问题的答案来看,在Access中似乎不太可能,但我的最佳选择可能是使用某种查询。我尝试了查询向导,发现交叉表查询与我上面描述的非常接近。但是,行标题中最多使用3个字段,而这里我有4个字段。并且,当没有指定值时(如上面示例中的C、D、F、G),它只留下一个空白,而不是将$0.00放入 更新(回应Remou提供样本数据的评论):以下是一些样本数据Ms access Access中VBA代码的改进,以实现类似透视表的功能,ms-access,vba,Ms Access,Vba,我在MS Access 2007中有一个数据表。每个记录有6个字段,数千条记录。我想制作一种类似透视表的对象。也就是说,如果前4个字段中的任意两行恰好相同,那么它们最终将分组到一行中。此透视表中的列标题将是第5个字段中的值,透视表中的值将是第6个字段,即美元金额。将第5个字段想象为字母A、B、C、D、E、F、G。因此,我开始的表格可能有一行,第5个字段中有A,第6个字段中有3.48美元。另一行可能在前4个字段中匹配,第5个字段中有B,第6个字段中有8.59美元。另一个可能在前4个字段匹配,第5个
ID a b c d e f
7 1 2 3 5 A 5
8 1 2 3 5 B 10
9 1 2 3 5 C 15
10 1 2 3 5 D 20
11 1 2 3 5 E 25
12 1 2 4 4 A 16
13 1 2 4 4 B 26
14 1 3 3 7 D 11
15 1 3 3 7 B 11
结果应该是:
a b c d an bn cn dn en Total
1 2 3 5 5 10 15 20 25 75
1 2 4 4 16 26 0 0 0 42
1 3 3 7 0 11 0 11 0 22
但是,当我复制并粘贴Remou提供的SQL时,我得到的唯一输出是
a b c d an bn cn dn en
1 2 3 5 5 10 15 20 25
这是我想要的,但是最好考虑数据库设计,因为这是一个电子表格解决方案。
SELECT t0.a,
t0.b,
t0.c,
t0.d,
Iif(Isnull([a1]), 0, [a1]) AS an,
Iif(Isnull([b1]), 0, [b1]) AS bn,
Iif(Isnull([c1]), 0, [c1]) AS cn,
Iif(Isnull([d1]), 0, [d1]) AS dn,
Iif(Isnull([e1]), 0, [e1]) AS en
FROM (((((SELECT DISTINCT t.a,
t.b,
t.c,
t.d
FROM table3 t) AS t0
LEFT JOIN (SELECT t.a,
t.b,
t.c,
t.d,
t.f AS a1
FROM table3 t
WHERE t.e = "A") AS a0
ON ( t0.d = a0.d )
AND ( t0.c = a0.c )
AND ( t0.b = a0.b )
AND ( t0.a = a0.a ))
LEFT JOIN (SELECT t.a,
t.b,
t.c,
t.d,
t.f AS b1
FROM table3 t
WHERE t.e = "B") AS b0
ON ( t0.d = b0.d )
AND ( t0.c = b0.c )
AND ( t0.b = b0.b )
AND ( t0.a = b0.a ))
LEFT JOIN (SELECT t.a,
t.b,
t.c,
t.d,
t.f AS c1
FROM table3 t
WHERE t.e = "C") AS c0
ON ( t0.d = c0.d )
AND ( t0.c = c0.c )
AND ( t0.b = c0.b )
AND ( t0.a = c0.a ))
LEFT JOIN (SELECT t.a,
t.b,
t.c,
t.d,
t.f AS d1
FROM table3 t
WHERE t.e = "D") AS d0
ON ( t0.d = d0.d )
AND ( t0.c = d0.c )
AND ( t0.b = d0.b )
AND ( t0.a = d0.a ))
LEFT JOIN (SELECT t.a,
t.b,
t.c,
t.d,
t.f AS e1
FROM table3 t
WHERE t.e = "E") AS e0
ON ( t0.d = e0.d )
AND ( t0.c = e0.c )
AND ( t0.b = e0.b )
AND ( t0.a = e0.a );
表3
ID a b c d e f
1 1 2 3 4 a €10.00
2 1 2 3 4 b €10.00
3 1 2 3 4 c €10.00
4 1 2 3 4 d €10.00
5 1 2 3 4 e €10.00
6 1 2 3 5 a €10.00
7 1 2 3 5 b
8 1 2 3 5 c €10.00
9 1 2 3 5 d €10.00
10 1 2 3 5 e €10.00
结果
有两行,因为前四列中只有两个不同的集合
a b c d an bn cn dn en
1 2 3 4 €10.00 €10.00 €10.00 €10.00 €10.00
1 2 3 5 €10.00 €0.00 €10.00 €10.00 €10.00
上述sql的工作方式是,它从表中选择四个定义列和货币列中的每一个,其中排序列具有特定的排序字母,并用排序字母标记货币列,然后组装这些子查询中的每一个,但是,您可以进行子查询并查看结果。最后一个是括号之间的部分:
INNER JOIN (SELECT t.a,
t.b,
t.c,
t.d,
t.f AS e1
FROM table3 t
WHERE t.e = "E") AS e0
所以,你是说我需要学习SQL。嗯,我想我今天会读到它。@Graphth SQL是让数据库上瘾的原因:)顺便说一句,上面的方法很有效,如果你想提供一些真实的字段名和示例数据,你可以得到一个剪切粘贴解决方案。我复制并粘贴了这段代码到一个数据库中,在那里我遵循了上面给出的规则。我用数据“table3”调用该表,并将字段标记为“a”、“b”、“c”、“d”、“e”和“f”。我运行了查询,它只给出了一行,尽管根据我的数据应该有15行。然而,正如我所描述的,它确实正确地收集了表3中的各种记录,并将它们放在这一行中。这是SQL中的一个小错误还是您认为我做错了什么?您只需要将内部连接更改为左连接。