0

複数のワークブックから特定のワークシートをマージするプログラムがあります。このプログラムでは、約 300 のワークブックを処理し、統合されたワークブックを作成する必要があります。統合されたワークブックでは、他のワークブックからコピーした各行にさらにいくつかのデータ ポイントを追加する必要があります。ターゲット ワークブックの行数は、おそらく 100,000 前後です。

名前、国、通貨など、他の列として追加する必要がある顧客に関連する他の多くのデータを含む別の XL があります。

1 つのワークブックには、1 人の顧客からのデータのみが含まれます。したがって、1 つのワークブックからコピーされたデータの場合、これらすべての列のデータは基本的に同じになります。

現在、各ワークシートからデータを貼り付ける際に、customerData ワークブックを開いて、customerID に基づいてデータを選択的にコピーし、対象のワークブックに貼り付けることを考えています。

コードは次のようになります。

For each workbook in the source Folder
    Open source workbook
    Copy the range from worksheet1
    Copy the customerID from worksheet2
    Open target workbook
    Paste range from source.worksheet1 in the target worksheet
    Fill the range in the target worksheet with the first column as customerID
    Open workbook with customer master data
    Copy data based on customerID
    Paste in the target worksheet using fill range

もう 1 つの方法は、すべてのワークシートからすべてのデータを貼り付けてから、顧客データのルックアップを行うことです。ここでの利点は、顧客のデータが複数のファイルに存在する可能性があるため、複数のルックアップを回避することである程度の効率が得られることです。また、顧客マスターデータファイルは一度だけ開く必要があります。

私が取ったアプローチが正しいかどうか、そして私にできる改善点があるかどうかを知りたい.

具体的には、次の質問があります。

  • 各ソース ファイルを開かないようにする方法はありますか?
  • ソース ワークブックのすべてのデータをメモリ内の配列に追加し、一度ターゲット ワークブックにコピーする方がよいでしょうか?
  • 配列アプローチを使用する場合、貼り付ける前に配列にルックアップを追加する必要がありますか、それとも宛先範囲のデータを貼り付けた後に行う必要がありますか?
4

1 に答える 1

1

コメントとしては長すぎるかもしれないので、これを返信として書きます。

1) ソース ファイルを開いてデータを取得することを回避する方法はありません。このような操作では、取得のために開くすべてのワークブックに対して、Excel の新しいインスタンスを作成し (CreateObject メソッド)、終了時に .Quit メソッドを適用してメモリから完全にクリアすることが非常に重要です。Workbook.close はご想像のとおり完璧ではありません (メモリは完全にクリアされません)。また、1 回のループで開いたり閉じたりしようとするワークブックの数が多いほど、特定の時点でアプリケーションがクラッシュしたりフリーズしたりする可能性が高くなります。点。

2) 読み取り/書き込み操作に最も時間がかかるため、その頻度を最小限に抑えることをお勧めします。最善の方法は、取得したワークブックごとにすべてのデータを一度に 1 つの範囲 (および配列) に読み取り、すべての操作をメモリ内で実行することです。必要な操作を実行したら、取得した配列を単一の範囲に書き込むことができます。
あなたが提案するように、すべてのワークブックを一度に配列にロードできます(私の知る限り、配列のサイズは利用可能なメモリの量にのみ制限されています。実用的な理由から、ファイルを閉じるたびに対象のワークブックにデータを転送します. 予期しないことが発生した場合は、コード全体を再実行する必要はありませんが、前回の場所から for next ループを設定できます.

3) バグが発生するたびにアプリケーションが停止するのを防ぎたい場合 (この量のデータを取得する場合に発生する可能性が高い)、次を使用します。

On Error goto ErrHandler
Err.Handler: 
    'Display error number / Description + place in logfile 
    Resume next 

エラーコード、説明、およびエラーが発生した場所を別の「ログ」ファイルに書き込む小さなエラーハンドラーを作成して、後で間違いを追跡できるようにすることをお勧めします。しかし、この方法でコードの実行中にコーヒーを飲むことができます。

4) ルックアップに関しては、あなたがやろうとしていることを正しく理解しているかどうか確信が持てません. 最も速いルックアップは、当然、ループが最も短いものです。入れ子になったループは通常、かなり高価です。確かに長い場合はそうです。
将来、ユーザー データベース (またはその他の RDBMS) に MS Access を使用することをお勧めします (「顧客 ID」と聞いたとき、これが最初に思い浮かびます)。パフォーマンスの分野での主な利点は、インデックスを適用してレコードに直接アクセスできることです。単純な SQL ステートメントを使用してクエリを実行するのは簡単です。VBA を使用して自分ですべてをプログラムし、配列をループ処理する必要がある場合よりもはるかに簡単です。SQL ステートメントを使用して、一般的な CRUD (レコードの作成、取得、更新、削除) 操作を実行できますが、それ以上の操作も実行できます。さらに、VBA を適用して追加の変換を処理することもできます。

実際のコードは提供していませんが、私の返信がお役に立てば幸いです。

于 2012-10-02T08:45:02.043 に答える