一天摘要的 VBA 访问查询

Posted

技术标签:

【中文标题】一天摘要的 VBA 访问查询【英文标题】:VBA Access Query for Day Summary 【发布时间】:2015-01-27 22:36:27 【问题描述】:

我一直在这个论坛上寻求 VBA 帮助,但这是我第一次自己发帖。

我正在尝试制作一份报告,提供存储在 Access 中的各种警报的摘要。我想每天提供每个警报的简单计数。我使用了一些 SQL 查询,但没有真正使用任何 Access。我认为 Access 可以从 Access 本身执行数据透视表。如果有更好的方法,请告诉我。

Set CommandQuery.activeConnection = conn
commandQuery.CommandText = _
   "TRANSFORM Count(FixAlarms.[Alm_NativeTimeLast]) AS CountOfAlm_NativeTimeLast " & _
   "SELECT FixAlarms.Alm_Tagname, FixAlarms.Alm_Desc " & _
   "FROM FixAlarms " & _
   "WHERE ((FixAlarms.Alm_Tagname) <> """")) AND FixAlarms.Alm_NativeTimeIn > CellTime " & _
   "GROUP BY FixAlarms.[Alm_Tagname], FixAlarms.Alm_Descr " & _
   "PIVOT Format([Alm_NativeTimeIn],""Short Date"")"
rec.Open commandQuery

这是我正在使用的代码。我不得不重新输入它,所以请原谅任何错字。它完成了我想要的大部分工作,但它没有给我任何关于每列是哪一天的指示。我需要在每一列上都有一个标题,以防有一天没有警报。我认为答案在于 PIVOT 的 IN 部分,但如果没有语法错误,我无法让它工作。我以为我所要做的就是添加

PIVOT Format([Alm_NativeTimeIn],""Short Date"") IN 01/20/15"

如果可以的话,请帮忙。

谢谢。

【问题讨论】:

【参考方案1】:

为了获得一整天的记录,即使是那些你需要创建这些天没有活动的记录。在访问中执行此操作的最简单方法是使用一组 UNION 语句为类似于此的日期创建一个假表:

SELECT #2015-01-20# as dt FROM dual
UNION ALL
SELECT #2015-01-21# as dt FROM dual
UNION ALL
SELECT #2015-01-22# as dt FROM dual

如果您在 Access 中尝试上述查询,它将不起作用,因为没有名为 dual 的表。您将不得不创建它。检查this SO 问题。

创建上述查询后,您可以将其与源表 LEFT JOIN。

TRANSFORM Count(FixAlarms.[Alm_NativeTimeLast]) AS CountOfAlm_NativeTimeLast 
SELECT FixAlarms.Alm_Tagname, FixAlarms.Alm_Desc 
FROM 
(SELECT #2015-01-20# as dt FROM dual
UNION ALL
SELECT #2015-01-21# as dt FROM dual
UNION ALL
SELECT #2015-01-22# as dt FROM dual) as dates LEFT JOIN
FixAlarms ON DateValue(FixAlarms.[Alm_NativeTimeIn]) = dates.dt
WHERE ((FixAlarms.Alm_Tagname) <> """")) AND FixAlarms.Alm_NativeTimeIn > CellTime 
GROUP BY FixAlarms.[Alm_Tagname], FixAlarms.Alm_Descr 
PIVOT Format(dates.dt, 'Short Date')

编辑:我必须补充一点,这不是实现它的唯一方法。另一种方法是使用Numbers 表。创建一个名为Numbers 的表,其中包含一个数字列n,并用数字0 到100 填充它(取决于您希望包含在查询中的最大天数)。那么您对dates 的查询将是:

SELECT DateAdd('d', n, #2015-01-20#) as dt FROM numbers where n

结果查询将是:

TRANSFORM Count(FixAlarms.[Alm_NativeTimeLast]) AS CountOfAlm_NativeTimeLast 
SELECT FixAlarms.Alm_Tagname, FixAlarms.Alm_Desc 
FROM 
(SELECT DateAdd('d', n, #2015-01-20#) as dt FROM numbers where n < 30) as dates LEFT JOIN
FixAlarms ON DateValue(FixAlarms.[Alm_NativeTimeIn]) = dates.dt
WHERE ((FixAlarms.Alm_Tagname) <> """")) AND FixAlarms.Alm_NativeTimeIn > CellTime 
GROUP BY FixAlarms.[Alm_Tagname], FixAlarms.Alm_Descr 
PIVOT Format(dates.dt, 'Short Date')

【讨论】:

查,谢谢你的回答。我不完全理解为什么当我已经有一个 Date 列可以使用时,我必须创建另一个列。真的,只要每列都有一个标题,我就可以不用空白列。然后我可以编写一个宏来放置它们并对其进行排序。我不明白为什么在 Access 执行查询时查询具有列名,但是当我将其复制到 VBA 时却没有。也许这是我缺少的一些连接设置? 如果您没有某个范围内所有日期的数据,则该数据不会出现在 select 语句中。因此,当您转换此选择语句时,将不会创建列,从而导致间隙。通过使用 LEFT JOIN,您可以确保至少为缺失的日期创建了一行。只需尝试上述查询,看看它们是否产生所需的结果【参考方案2】:

当使用PIVOT columnName IN (ValueList)ValueList

    括号内 带引号 逗号分隔

所以你是

PIVOT Format([Alm_NativeTimeIn],""Short Date"") IN 01/20/15"

需要成为

PIVOT Format([Alm_NativeTimeIn],""Short Date"") IN (""01/20/15"")

话虽如此,这不会在 IN 语句中使用 PIVOTS 过滤您的记录。您仍然需要使用 WHERE 子句。

如果最终目标是从左到右表示您的数据,那么这将起作用。但是,将这项工作作为报告工作将是很多额外的工作,因为您的控件不会绑定到可预测的列。列名会因不同的参数而改变。

您可以将其保留为传统查询(未转置)并更轻松地报告它。如果您是直接向用户显示网格或导出到 Excel,那么这不是问题。

【讨论】:

【参考方案3】:

所以,我只想在我的数据透视表中添加一个标题,告诉我特定列的日期。 我没有显示的部分代码是我正在使用 rec.getrows 将我的所有数据移动到一个更简单的数组变量中。虽然这包含来自 Access 的所有数据,但它没有任何标题来告诉我什么是标记名、什么是描述以及什么是哪个日期。

我发现在 fields.item(n) 下的记录集本身中有一个 Name 属性。这个名称告诉我列数据的来源或数据的日期。使用此功能和一个简单的日期(日期)函数,我能够制作汇总所有警报的月度报告。

感谢你们的帮助,但我对问题的描述不是很清楚,就是想多了。

【讨论】:

以上是关于一天摘要的 VBA 访问查询的主要内容,如果未能解决你的问题,请参考以下文章

Excel VBA 查询访问失败

访问 VBA 查询

使用 VBA 访问查询和报告?

访问 SQL Server 的 VBA 查询

VBA根据查询运行带有参数的访问报告

使用 VBA 访问更新查询