2

好的,所以我正在尝试从 C# 自动化 Microsoft Access。显然,您不能在 VBA 本身中异步执行 VBA 代码,但我的想法是使用委托从 C# 强制执行此操作。

我们有一个遗留报告系统,它运行数百个设计不良的查询来获取信息,这些查询在宏内部同步运行。每个查询都是使用 MS Access 查询设计器设计的,并通过 ODBC 查询 MySql 数据库。它们需要 2-3 分钟才能运行,并且宏可能包含 <=20 个查询,这意味着宏将需要一个小时的大部分时间来运行。如果我运行这些异步,我可以在几分钟内运行整个宏。

我的完整 C# 代码如下:

using System;
using Microsoft.Office.Interop.Access;

namespace AsyncVBA
{
    class Program
    {
        private static Application ap;
        private delegate void ExportThread(string queryName, string exportLocation);

        private static int count;

        static void Main(string[] args)
        {
            var dbName = @"C:\Users\JMK\Desktop\MyDatabase.accdb";
            count = 0;

            ExportThread queryThread = new ExportThread(ExportQuery);

            ap = new Application();
            ap.OpenCurrentDatabase(dbName);

            queryThread.BeginInvoke("qryOne", @"C:\Users\JMK\Desktop\x\one.xlsx", null, null);
            queryThread.BeginInvoke("qryTwo", @"C:\Users\JMK\Desktop\x\two.xlsx", null, null);
            queryThread.BeginInvoke("qryThree", @"C:\Users\JMK\Desktop\x\three.xlsx", null, null);
            queryThread.BeginInvoke("qryFour", @"C:\Users\JMK\Desktop\x\four.xlsx", null, null);
            queryThread.BeginInvoke("qryFive", @"C:\Users\JMK\Desktop\x\five.xlsx", null, null);
            queryThread.BeginInvoke("qrySix", @"C:\Users\JMK\Desktop\x\six.xlsx", null, null);
            queryThread.BeginInvoke("qrySeven", @"C:\Users\JMK\Desktop\x\seven.xlsx", null, null);
            queryThread.BeginInvoke("qryEight", @"C:\Users\JMK\Desktop\x\eight.xlsx", null, null);
            queryThread.BeginInvoke("qryNine", @"C:\Users\JMK\Desktop\x\nine.xlsx", null, null);
            queryThread.BeginInvoke("qryTen", @"C:\Users\JMK\Desktop\x\ten.xlsx", null, null);

            while (count < 10)
            {
                Console.ReadLine();
            }

            ap.CloseCurrentDatabase();
        }

        private static void ExportQuery(string queryName, string exportLocation)
        {
            ap.DoCmd.TransferSpreadsheet(AcDataTransferType.acExport, AcSpreadSheetType.acSpreadsheetTypeExcel9, queryName, exportLocation);
            count++;
        }

    }
}

我目前有两个问题,第一个是我的代码似乎仍在同步执行,这可能与 MS Access 的限制有关。我猜 MS Access 在收到请求或其他请求时正在对请求进行排队。第二个不太重要的问题是我的计数似乎没有增加。

我哪里错了?

谢谢

4

3 回答 3

7

仅从使用Access作为前端的大量经验来看,最好的是将所有查询更改为Pass-through查询并用mySQL语法重写它们。

当前方法花费这么长时间的原因可能是通过网络传递的数据集远远大于它需要的大小。Access 会传递 mySQL DB 可以解释的内容,然后在到达时应用其余的 sql 语法。对于大型数据集,它的效率非常低。

于 2012-10-10T18:04:20.727 回答
3

实际上,启动 word、Excel、power point 或任何办公套件都不会异步运行任何东西。事实上,如果你创建了一个 SQL server 实例,你会发现同样的事情。(将 SQL 命令发送到 SQL SEPARATE 进程与创建进程内实例之间存在很大差异。

我会考虑将这些数据写入一个文本文件,甚至是一个临时表,然后 shell() 输出一个正在启动的应用程序实例,运行一系列查询。您甚至可以在这里创建一个执行这些命令的 windows 脚本。这样您就可以获得一个单独的实例和线程,因此您的应用程序将不必等待。

于 2012-04-15T21:44:08.413 回答
1

Microsoft Access 中没有任何东西被设计为与其他任何东西同时运行。我很确定,当您成功打开 Access 数据库时,您将获得对所有系统表的排他锁。我看不出它如何以任何其他方式工作。

更好的方法是从 Access 数据库中提取 SQL。您说每个查询都是使用查询设计器设计的(我认为您的意思是设计视图),但它仍然具有您可以使用的 SQL。只需从设计视图切换到 SQL 视图,就可以了

于 2012-04-15T13:27:19.923 回答