【问题标题】:Improvement of VBA code in Access to do something like a pivot table改进 Access 中的 VBA 代码以执行数据透视表之类的操作
【发布时间】:2011-12-22 03:11:39
【问题描述】:

我在 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 提供示例数据的评论):这是一些示例数据。

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

【问题讨论】:

    标签: ms-access vba


    【解决方案1】:

    我认为这是您想要的,但最好考虑数据库设计,因为这是一个类似电子表格的解决方案。

    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 ); 
    

    Table3

    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 行。但是,它确实正确地收集了 table3 中的各种记录,并将它们放入这一行,就像我描述的那样。是 SQL 中的小错误还是您认为我做错了什么?
    • 您只需将 INNER JOIN 更改为 LEFT JOIN。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-29
    • 2013-05-09
    • 2016-05-17
    • 1970-01-01
    • 2019-11-01
    • 1970-01-01
    • 2010-10-20
    相关资源
    最近更新 更多