4

我正在开发一个设备管理系统,前端使用 MS Access .mdb 文件,后端使用 SQL Server 2008。如果需要,我可以将前端转换为 MS Access 2010 文件。

我创建了一个日历表单,用户可以在其中查看预订、退出或过期的设备。它看起来像这样:

在此处输入图像描述

我使用 42 个子表单制作了这个,不幸的是这很慢。使用上面显示的数据,加载只需要大约 5 秒,但是一旦我使用真实数据,它就开始真正陷入无法接受的困境。我试图通过将子表单的源对象保持空白直到它们显示出来来提高效率,并且直到此时才加载记录源。这足以使上面看到的示例运行得相当快,但对于真实数据来说仍然不够。

所以我想做的是,要么找到一种在仍然使用子窗体的同时提高效率的方法,找到另一个代替子窗体工作的控件,或者用列表框切换子窗体,但不知何故仍然能够格式化颜色的行。我知道这对于列表框来说是不可能的,但我是一名程序员,如果不会浪费我太多时间,我愿意尝试子类化列表框来做到这一点。不幸的是,我从来没有做过任何 vba 子类化,所以我需要指出一些好的资源才能这样做。

设置每天子窗体的记录源的代码如下:

f("sub" & X & Y).Form.RecordSource = "SELECT * " & _
                                     "FROM QRY_Calendar " & _
                                     "WHERE CDate(StartDate) <= #" & curDate & "# " & _
                                     "AND ((EndDate IS NULL OR CDate(EndDate) >= #" & curDate & "#)" & _
                                     IIf(CDate(curDate) <= Date, " OR ((Date_In IS NULL OR CDate(Date_In) >= #" & curDate & "#) AND Date_Out IS NOT NULL)", "") & ") " & _
                                     "ORDER BY IIF(Date_Out Is Not Null And (Date_In Is Null Or CDate2(Date_In)>=#" & curDate & "#) And CDate2(EndDate)<#" & curDate & "#,0,iif(CDate2(Date_Out)<=#" & curDate & "# And (Date_In Is Null Or CDate2(Date_In)>=#" & curDate & "#),1,2)), ID"

QRY_Calendar 看起来像这样:

SELECT B.ID, Person, Initials, ProjectNum & '-' & ProjectYear & '-' & Format(TaskNum,'000') AS Project, Sign_Out_Code, Value AS Type, StartDate, EndDate, Date_Out, Date_In
FROM (((TBL_Booking AS B INNER JOIN TBL_Person AS P ON B.PersonID = P.ID) INNER JOIN LKUP_List AS T ON B.EquipTypeID = T.ID) LEFT JOIN TBL_Usage AS U ON B.ID = U.BookingID) LEFT JOIN TBL_Equipment AS E ON U.Equipment_ID = E.ID;

表 TBL_Booking 中的 StartDate 和 EndDate 是预订的开始和结束,表 TBL_Usage 中的 Date_Out 和 Date_In 是注销的开始和结束。每个注销都通过外键 BookingID 链接到预订。如果 Date_In 为 NULL,则表示设备当前已注销。

LKUP_List 是我几年前开始工作之前的一个名称不佳的表,我从来没有费心去改变它。它包含设备类型的列表(除其他外)。预订是针对设备类型而非特定项目的,当用户注销其设备时,会在 TBL_Usage 中创建一条与特定设备相关联的记录。

如果有人对我应该采取哪个方向以及我可以在哪里寻求指导有任何想法,我将不胜感激。

4

5 回答 5

3

首先,42 个子表单的加载速度非常快,事实上我已经这样做了很多年,42 个子表单的加载时间实际上是瞬时的。

因此,这表明这里的读者可以忽略这里的一些评论,这些评论表明,与具有 NEAR 直接能力的 Windows 高性能桌面应用程序相比,基于脚本或基于文本的解释系统(如 HTML)在某种类型的浏览器渲染系统中运行速度更快直接写入视频显卡。

请记住,如果您了解 Windows 桌面应用程序可以直接写入视频卡的简单和基本知识,那么很少有人会尝试比较并建议如果我们要比较 HTML 中的渲染系统在速度方面比较这里有两种不同的架构。

所以这里真正的问题是can日历可以运行多快,42个子表单会是个问题吗?

答案很简单,42 个子表格不是问题,而且速度很快!

我的以下 Access 日历几乎立即呈现。

在此处输入图像描述

即使在生产环境中,我的上述 Access 日历也已使用多年。即使日历每天都有更多无法显示在屏幕上的数据,加载时间也是即时的。其中很多正在运行,其中桌面(客户端)通过标准 Internet 连接到在网站上运行的 SQL Server 的托管版本访问 SQL Server 后端。即使在这种带宽更有限的情况下,日历的加载时间和响应也几乎是即时的。因此,无论我是否使用 accDB(基于文件)后端、使用 SQL 服务器作为后端,甚至更令人惊奇的是,该表单都可以很好地与我的许多通过常规 Internet 运行此 Access 日历的客户配合使用后端是在托管网站上运行的 SQL 服务器的连接。

上面的设计有 42 个子表单,正如没有数据所指出的,子表单加载绝对接近即时。说明这一点很重要,因此我提供了一些现实世界和事实证据来贬低那些显然不掌握和理解基本计算机体系结构的人在这里发表的其他评论。因此,这些人会建议加载 42 个子表单在某种程度上会降低软件速度,而事实上我可以很容易地证明情况并非如此。因此,这里其他人的证人和证词可以被证明是没有价值的,因此这种观点是基于对计算机的基本操作如何在我们的行业中工作缺乏了解。HTML 无法与此处的此类设置进行比较。

现在谈到基于 Web 的 Access 允许 Web 发布,然后我发布了以下视频,其中包含在 Web 浏览器中运行的 Access 内置日历。这个基于浏览器的日历仅使用 Access 构建,没有任何第三方工具。

http://www.youtube.com/watch?v=AU4mH0jPntI

上述视频的结果显示了此日历应用程序的黄油平滑和即时响应的基于 Web 的版本。

现在我应该指出,在上述基于 Web 的示例中,我不使用 42 个子表单,因为在 Web 浏览器中,每个表单都是一个单独的框架,并导致重新呈现从服务器发送的表单。这意味着对于基于 42 个子表单的设计的 Access web 是不可能的。您将在渲染方面遭受巨大的性能损失(即使没有数据,因为 XMAL 表单是按需加载的以节省时间,但在这种情况下,这种设置会受到伤害)。

但是,正如视频所示,基于 Web(也适用于基于客户端)的解决方案是填写一个表格,在该表格中将文本框绑定到该表格。因此,具有一个记录显示正如上面的视频中所指出的那样,并且显示了这样的结果意味着接近即时的响应,并且即使在网络浏览器中也是如此。

我强调基于 WEB 的应用程序,因为该视频是仅使用 Access 构建的,没有其他工具。

现在回到性能问题和基于客户端的应用程序。当然,我们现在知道加载 42 个子表单不是问题。

当然,问题是运行 42 个单独的 SQL 查询,使用各种表达式将数据提取到这些子表单中,这是瓶颈和性能下降的地方。因此,如果我们使用 42 个文本框,甚至 42 个列表框,这个性能问题不会改变。

所以问题在于尝试执行 42 个单独的 SQL 查询。请记住,每个 SQL 查询都需要时间来解析、检查语法,然后构建查询计划等。事实上,在数据甚至开始为那个给定查询流动之前,必须发生相当多的操作。事实上,我发现一个查询在带宽方面可能是大约 10,000 行数据流的成本。

基于以上信息,我设计的这 42 个子表单之所以可以立即加载和执行,是因为我只执行一个查询来返回整个月的数据。换句话说,我使用显示的开始日期和结束日期执行查询。然后,我运行 VBA 代码将生成的 reocrdset 中的数据处理为子表单 1 到 42。因此,VBA 代码将生成的记录集数据填充到 42 个子表单中。因此,这是确保高性能计算且不会减速的关键概念和建议。

所以总结和总结:

性能瓶颈不是使用 42 个子表单,而是拥有 42 个记录集和 42 个查询,以及可能需要计算 42 次的附加代码和表达式。消除 42 次查询和 42 次并不得不重新执行此类 SQL 语句,这个瓶颈将几乎消失。

我敢说,使用 42 个列表框,甚至只是 42 个文本框并继续执行 42 条这样的 SQL 语句,不会产生任何有价值的性能改进。

于 2012-11-18T00:11:12.533 回答
3

不久前问了一个与日历相关的问题:在Access中创建一个'日历矩阵'

也就是说,您可能永远无法使用绑定到非平凡查询的 43 个子表单来获得良好的性能。

可能的小改进

您并不是说您的数据是否在后端服务器上,在这种情况下,每个子表单都必须通过网络获取数据。
如果是这种情况,您最好对服务器进行一次查询以提取所有数据并将其缓存在前端。然后,您只需对本地表进行简单的过滤,这应该会更快,尽管 42 个子表单可能会成为性能的一大瓶颈。

一个简单的INSERT INTO查询可以帮助您入门,前提是您已经创建了一个myCacheTable基于正常查询返回的数据调用的本地表。

轻量级控件

您可能应该尝试的第一件事是使用 venerable listbox
它相当轻巧,并且有很多方法可以配置它们。
如果你将它与我上面提到的服务器缓存数据结合起来,你可以获得更好的性能。

列表框示例

支持 Web 的控件

正如HelloW 所TextFormat = RichText提到的,简单地使用设置为的文本框并为它们提供简单的 HTML(它不支持太多)来格式化内部数据可能是一个好主意:

RichText 文本框示例

完整的网页

可能设置起来有点复杂,但在 UI 方面难以击败,可能是使用现有的 Javascript 库,如FullCalendar,或者将您自己的 html 直接注入浏览器文档(您可以使用 simple<table>来格式化日历)。

下面是一个示例在线日历WebBrowser在 Access 表单中的控件内的样子:

Access 中的 Web 日历视图

于 2012-11-16T04:37:19.153 回答
2

我同意这在 HTML 中效果最好的想法。
将每个子表单替换为富文本格式的文本框。然后在表单加载(或其他一些事件)上获取该月的记录集并循环通过它将文本添加到每个文本框。可用的 HTML 子集通常足以获得您需要的大部分格式。

注意事项

  1. 就 vba 而言,这将需要一些真正的思考。很可能您对此感到满意,因为您已经做到了这一点。
  2. 只有一个查询,所以速度可以更可接受
  3. 您的关键 HTML 标签将是<br>和颜色标签
  4. 您将无法仅更改文本颜色的背景颜色(我可能在这里错了)
于 2012-11-16T03:48:01.950 回答
2

另一种解决方案是制作许多文本框控件,每个控件代表日历日中的记录。

您运行 1 个查询 - 快!

在 VBA 中循环遍历每个文本框控件并为其分配水平和垂直位置、内容(值)、格式、可见性(您不需要显示没有数据的控件)。

不利的一面是您必须提前确定需要多少个文本框控件,并且可能不足以满足查询传递的所有记录。

为了克服这个问题,您可以任意决定您有 100 个控件,仅首先显示记录集中更重要的记录(例如过期),并记下“并非所有记录都显示”。如果用户想查看所有记录,他单击特定日期,将打开更详细的子表单,其中显示该日期的所有记录。

我从未在日历中尝试过,但我有一个带有甘特图的表格,显示时间条。每个时间栏都是一个文本框控件。我有 120 个控件,它可以立即工作。

于 2013-09-19T02:51:48.320 回答
0

另一种解决方案是使用Tcal,我刚刚更新到版本1.4.2 什么是Tcal?Tcal 是具有完整图形界面的客户端-服务器跨平台日历。使用 TcalServer 和 TCP/IP,Tcal 将事件、截止日期和工作时间记录到您公司的个性化 FileMaker Pro、Microsoft Access 或 MySQL 数据库文件中。您可以为您的活动分配资源和工作名称、查看其他资源日历、接受或拒绝邀请。Tcal 适用于 Mac OSX 和 Window(7 或 XP),并且是免费的,最多可供 2 个连接用户使用。你可以在这里找到 Tcal:http ://www.tcal.it/eng/index.html

于 2015-02-15T13:10:00.773 回答