2

わかりましたので、C# から Microsoft Access を自動化しようとしています。明らかに、VBA 自体で VBA コードを非同期的に実行することはできませんが、私の考えは、デリゲートを使用して C# からこれをブルート フォースすることでした。

情報を取得するために何百もの不適切に設計されたクエリを実行する従来のレポート システムがあり、これらのクエリはマクロ内で同期的に実行されます。各クエリは、MS Access クエリ デザイナーを使用して設計され、ODBC を介して MySql データベースにクエリを実行します。実行には 2 ~ 3 分かかり、マクロには 20 以下のクエリが含まれる場合があります。つまり、マクロの実行には 1 時間ほどかかります。これらを非同期で実行すると、マクロ全体を数分で実行できます。

私の完全な 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++;
        }

    }
}

現在、2 つの問題があります。1 つ目は、コードがまだ同期的に実行されているように見えることです。これは、MS Access の制限に関係している可能性があります。私は、MS Access が要求を受信したときに要求をキューに入れていると推測しています。2 つ目の、あまり重要でない問題は、カウントが増加していないように見えることです。

どこが間違っていますか?

ありがとう

4

3 に答える 3

7

フロントエンドとしてのAccessの多くの経験から言えば、すべてのクエリをパススルークエリに変更し、mySQL構文で書き直すのが最善です。

現在の方法に非常に時間がかかる理由は、おそらくネットワークを介して渡されるデータセットが必要以上に大きいためです。Accessは、mySQL DBが解釈できるものを渡し、到着時に残りのSQL構文を適用します。大規模なデータセットには非常に非効率的です。

于 2012-10-10T18:04:20.727 に答える
3

実際には、ワード、エクセル、パワー ポイント、またはオフィス スイートのいずれかを起動しても、非同期で実行されることはありません。実際、SQL サーバーのインスタンスを作成すると、同じことがわかります。(インプロセス インスタンスの作成とは対照的に、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 に答える