Access VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


829 / 2272 ツリー ←次へ | 前へ→

【9912】インポート時の重複データ処理 みう 07/10/10(水) 11:34 質問[未読]
【9913】Re:インポート時の重複データ処理 小僧 07/10/10(水) 13:08 回答[未読]
【9914】Re:インポート時の重複データ処理 みう 07/10/10(水) 14:10 質問[未読]
【9915】Re:インポート時の重複データ処理 小僧 07/10/10(水) 14:51 回答[未読]
【9916】Re:インポート時の重複データ処理 みう 07/10/10(水) 17:06 質問[未読]
【9917】Re:インポート時の重複データ処理 小僧 07/10/10(水) 17:34 回答[未読]
【9918】Re:インポート時の重複データ処理 みう 07/10/10(水) 18:07 質問[未読]
【9919】Re:インポート時の重複データ処理 小僧 07/10/10(水) 18:51 回答[未読]
【9921】Re:インポート時の重複データ処理 みう 07/10/11(木) 11:03 質問[未読]
【9922】Re:インポート時の重複データ処理 みう 07/10/11(木) 13:32 質問[未読]
【9923】Re:インポート時の重複データ処理 小僧 07/10/11(木) 15:09 回答[未読]
【9924】Re:インポート時の重複データ処理 みう 07/10/12(金) 11:52 質問[未読]
【9925】Re:インポート時の重複データ処理 小僧 07/10/12(金) 18:36 回答[未読]
【9926】Re:インポート時の重複データ処理 小僧 07/10/15(月) 10:06 回答[未読]
【9927】Re:インポート時の重複データ処理 みう 07/10/15(月) 16:04 お礼[未読]

【9912】インポート時の重複データ処理
質問  みう  - 07/10/10(水) 11:34 -

引用なし
パスワード
   たびたびお世話になります。
教えていただきたいです。

現在ExcelのデータをAccessにインポートするという処理をVBAでかいているのですが。。。

・重複データを検索する
・見つかったらダイアログボックスを出して上書きするか、キャンセルするかを表示(これはできます。。。)

というかんじの機能をつけたいのですが。。。

どうやればいいでしょうか。。。。

ご指導お願いいたします。

【9913】Re:インポート時の重複データ処理
回答  小僧  - 07/10/10(水) 13:08 -

引用なし
パスワード
   ▼みう さん:
こんにちは。

まず、画面上部の

>本サイトの基本方針をまとめました。こちら をご一読ください。

の こちら のリンク先をお読みになって下さい。

> してはいけない質問について

の 丸投げに相当していませんか?

御自分でどこまでできていて、何が解らないのかを明確にご提示すれば
もっと回答がつきやすくなると思われます。


さて、実際の方法なのですが、
A) 取り込む前にExcelを精査する
B) 取り込みながら重複をチェックする
C) とりあえず取り込んだ後に重複をチェックする

等の方法が考えられるかと思われます。


また

>見つかったらダイアログボックスを出して上書きするか、キャンセルするかを表示

とありますが、複数件見つかった場合
全てのレコードに対して「上書き」「キャンセル」を1回表示するのか
1件1件について問い合わせを行うのかによって方法は変わってくるかと思われます。


当方が行うとすれば C) の方法になりますが、
実際の取込先のテーブルとまったく同じ構造を持ったテーブル(ワークテーブル)を用意して

1) いったんワークテーブルに全てのデータを取り込む、
2) 重複レコードに対しての処理を行う
3) 取込先テーブルへとインポートを行う

という様な流れにするかと思われます。

【9914】Re:インポート時の重複データ処理
質問  みう  - 07/10/10(水) 14:10 -

引用なし
パスワード
   小僧 さん

> してはいけない質問について
>
>の 丸投げに相当していませんか?
>
>御自分でどこまでできていて、何が解らないのかを明確にご提示すれば
>もっと回答がつきやすくなると思われます。

今見返してみればそうですね・・・
申し訳ないです。
丸投げをするつもりで書いたわけでなく、もっと細かく書くべきでした。。。

>A) 取り込む前にExcelを精査する
>B) 取り込みながら重複をチェックする
>C) とりあえず取り込んだ後に重複をチェックする
>
>等の方法が考えられるかと思われます。
>

考えとしては、Bに近いのかなと思います。

>1) いったんワークテーブルに全てのデータを取り込む、
>2) 重複レコードに対しての処理を行う
>3) 取込先テーブルへとインポートを行う
>
>という様な流れにするかと思われます。

申し訳ありません。ワークテーブルというのは消してもいいようなテーブルを他に作るという感じでしょうか?

まず、VBAでどう書くかとか以前の段階で、教えてもらいたかったのもあります。

いろいろネットなどで勉強したなか、クエリにいれて比較して削除というのがありました。
これはVBAじょうでもできるのでしょうか?
VBAの中身の話ではなく申し訳ないです。。。。

【9915】Re:インポート時の重複データ処理
回答  小僧  - 07/10/10(水) 14:51 -

引用なし
パスワード
   ▼みう さん:
こんにちは。

> ワークテーブルというのは消してもいいようなテーブルを
> 他に作るという感じでしょうか?

はい、その通りです。

取込先のテーブルを右クリックして「コピー」
データベースウィンドウの空白の所で
右クリックで「貼り付け」と行うと

貼り付けの設定で
・テーブル構造のみ

というのがあるので、それを使ってみましょう。

テーブル名は

W_取込テーブル

のように接頭に「W_」などと付けて上げると
見た目でワークテーブルと言うのが解りやすくなりますね。


毎回テーブルを消したり作ったりするのは
あまりAccessに良くない(ゴミが残ったりする)ので
中のレコードだけ消したり追加したりするのが良いかと思われます。


> クエリにいれて比較して削除というのがありました

Excel のデータをそのままクエリで比較するのは
結構テクニックが必要になります。

いったんワークテーブルに取り込んでから
ワークテーブルと取り込み先のテーブルの比較を行う方が良さそうですね。

その際の手段としてクエリを使う方法もあります。
(次の段階ですね)

Excelからワークテーブルに取り込むには
Transferspreadsheet メソッドを使うと
ある程度自動に取り込む事ができます。

取り込む前に初期化として
全レコードを消す処理を作っておいたほうが無難ですね。

まずはワークテーブルに取り込む所まで、
それができましたら「比較してメッセージを…」の箇所を
作られてみてはいかがでしょうか。

【9916】Re:インポート時の重複データ処理
質問  みう  - 07/10/10(水) 17:06 -

引用なし
パスワード
   ▼小僧 さん:

>取込先のテーブルを右クリックして「コピー」
>データベースウィンドウの空白の所で
>(中略)
>毎回テーブルを消したり作ったりするのは
>あまりAccessに良くない(ゴミが残ったりする)ので
>中のレコードだけ消したり追加したりするのが良いかと思われます。

わかりやすく教えていただきありがとうございます。


>> クエリにいれて比較して削除というのがありました
>
>Excel のデータをそのままクエリで比較するのは
(中略)
>まずはワークテーブルに取り込む所まで、
>それができましたら「比較してメッセージを…」の箇所を
>作られてみてはいかがでしょうか。


結果としましては、データの量が多いので(数百万単位)
手でコピペはできなかったので、

  DoCmd.DeleteObject , W_ワークテーブル
  DoCmd.CopyObject , "W_ワークテーブル", acTable, tblname

ワークテーブル内のデータをまずすべて消し、取引先のテーブルを
そのままコピーという感じになりました。

インポート文は元から作成してあったので、(かなり苦労しました。。。)
上の文を組み込みました。

ここから比較にはいりたいのですが、
やりかたはいろいろあるとおもうのですが、

・ワークテーブルを初期化
・取引先のテーブルをワークテーブルにコピー
・ワークテーブルに今回取り込みたいデータをインポート
・重複チェック(ここで重複があればメッセージ)
・上書きならワークシートないでまず上書き
・ワークシートないのデータを取引先テーブルに貼り付け(ここはそのまま上書き)


みたいなかんじでいいんでしょうか?
取引先データをこわさないようにするみたいなかんじに
データを取り込むみたいなかんじになりますが・・・

よろしくお願いします。

【9917】Re:インポート時の重複データ処理
回答  小僧  - 07/10/10(水) 17:34 -

引用なし
パスワード
   ▼みう さん:
こんにちは。

まず…。

前回の投稿で書くのを忘れてしまったのですが、
Accessのファイルは壊れやすいです。

特に今回の様に試行錯誤しながら色々操作を行っていると
応答がなくなってしまったり、
その為に強制終了をせざるを得なかったりと
ファイルが壊れる要因が多々ありえます。

必ず元ファイルのバックアップをとっておいて下さいね。

また、これも初めの方の投稿で書いておくべきでしたが
みうさんがお使いのPCの OS、Accessのバージョンによって
VBAのコードが変わってくる場合もあります。

ご質問の際には OS や Access のバージョンを明記する様にしましょう。


>・ワークテーブルを初期化
>・取引先のテーブルをワークテーブルにコピー
>・ワークテーブルに今回取り込みたいデータをインポート
>・重複チェック(ここで重複があればメッセージ)
>・上書きならワークシートないでまず上書き
>・ワークシートないのデータを取引先テーブルに貼り付け(ここはそのまま上書き)


・W_ワークテーブルの初期化
・W_ワークテーブルに今回取り込みたいデータをインポート
・W_ワークテーブルと本来インポートしたいテーブルの比較

となります。


前回の投稿で述べたのですが、
重複レコードが複数あった場合
「上書き」か「キャンセル」か選ばせるとの事ですが、

A) 1行ずつ確認のメッセージ?
B) 全体に対しての「上書き」「キャンセル」の処理?

また B) であるのならば
重複しているレコードのみキャンセルなのか、
それとも全レコードの取り込みをキャンセルするのかによって
仕様が変わってきますね。

その後
・上書きの場合は取りこみ先テーブルから重複となるレコードを削除
 キャンセルの場合は仕様によって…。

・ワークテーブルのデータを取り込み先テーブルへインポート

となりますね。


> データの量が多いので(数百万単位)

データ量が多いとプログラムの実行に時間も掛かってしまうので
まずは実験の為に数千レコードぐらいに減らした
実験用のMDBファイル、CSVファイルを作って
うまく行った後に本番データで試してみてはいかがでしょうか。


上記のキャンセル仕様に関するご回答と、
最終的に取り込みたいテーブルの名前、
重複かどうかを判断するフィールドの名前などあると
次回の回答が付けやすくなると思われます。

【9918】Re:インポート時の重複データ処理
質問  みう  - 07/10/10(水) 18:07 -

引用なし
パスワード
   ▼小僧 さん:

>特に今回の様に試行錯誤しながら色々操作を行っていると
>応答がなくなってしまったり、
>その為に強制終了をせざるを得なかったりと
>ファイルが壊れる要因が多々ありえます。
>
>必ず元ファイルのバックアップをとっておいて下さいね。

Accessは壊れやすいのですね。。。
今回は壊れてもいいように元ファイルからコピーしたやつで
作成しています!なので、まーこわれてもいーかぐらいないきおいで
色々やってます^^


>データ量が多いとプログラムの実行に時間も掛かってしまうので
>まずは実験の為に数千レコードぐらいに減らした
>実験用のMDBファイル、CSVファイルを作って
>うまく行った後に本番データで試してみてはいかがでしょうか

これもですが、いきなり本番データとは恐れ多いので、
適当に2項目くらいで5000件くらいのデータをつくり、
それでテストしてます。
本番データはかなりの量なので、処理が遅くなるのはしょうがないと
了解は得ています!


>また、これも初めの方の投稿で書いておくべきでしたが
>みうさんがお使いのPCの OS、Accessのバージョンによって
>VBAのコードが変わってくる場合もあります。
>
>ご質問の際には OS や Access のバージョンを明記する様にしましょう。

たしかにそうですね・・・
申し訳ないです・・・・
OS:XP
Accessバージョン:2003

になります!!


>・W_ワークテーブルの初期化
>・W_ワークテーブルに今回取り込みたいデータをインポート
>・W_ワークテーブルと本来インポートしたいテーブルの比較

ということは、
・取引先のテーブル
・W_ワークテーブル
・今回インポートしたいデータのテーブル

の3つが必要ということで大丈夫でしょうか???


>前回の投稿で述べたのですが、
>重複レコードが複数あった場合
>「上書き」か「キャンセル」か選ばせるとの事ですが、
>
>A) 1行ずつ確認のメッセージ?
>B) 全体に対しての「上書き」「キャンセル」の処理?

回答していませんでしたね。。。
またまた申し訳ないです。。。。
今回はBの仕様でいきたいと思っています。


>また B) であるのならば
>重複しているレコードのみキャンセルなのか、
>それとも全レコードの取り込みをキャンセルするのかによって
>仕様が変わってきますね。

>その後
>・上書きの場合は取りこみ先テーブルから重複となるレコードを削除
> キャンセルの場合は仕様によって…。
>
>・ワークテーブルのデータを取り込み先テーブルへインポート
>
>となりますね。
>

考えとしては、
重複データがあった場合、メッセージをだし、
・上書きの場合:取込先テーブルの重複したデータを削除し、今回取り込んだデータを追加
・キャンセルの場合:取込じたい終了。(Exit subなど。。。)


>上記のキャンセル仕様に関するご回答と、
>最終的に取り込みたいテーブルの名前、
>重複かどうかを判断するフィールドの名前などあると
>次回の回答が付けやすくなると思われます。


最終的に取り込みたいテーブル:test
ワークテーブル:W_ワークテーブル

フィールド名1:日付
フィールド名2:社員番号

この場合、重複データがあるとしたい内容は、
日付、社員番号の2つが一致したときに重複データとしたいのですが。。。


何回もすみません。
かつ質問だらけで申し訳ないです。
ヒントや、アドバイス教えてください。

【9919】Re:インポート時の重複データ処理
回答  小僧  - 07/10/10(水) 18:51 -

引用なし
パスワード
   ▼みう さん:
こんにちは。


>・取引先のテーブル
>・W_ワークテーブル
>・今回インポートしたいデータのテーブル

・取引先のテーブル
・W_ワークテーブル
・今回インポートしたいデータの「CSVファイル」

ですね。^^


流れとしては例えば

Option Compare Database
Option Explicit

Private Sub コマンド0_Click()
    
  If DataImport = False Then
    MsgBox "処理を中断します"
    Exit Sub
  End If
  
  '--------------------
  '後処理?
  '--------------------
  
  
End Sub


Function DataImport() As Boolean
Dim strSQL As String


'W_ワークテーブルの初期化
  strSQL = "DELETE FROM W_ワークテーブル"
  CurrentDb.Execute strSQL, dbFailOnError


'------------------------------------
'インポート処理、その後重複がみつかる
'------------------------------------

  If MsgBox("処理を中止しますか?", vbCritical + vbOKCancel) = vbCancel Then
    DataImport = False
    
  Else
  
  '------------------------------
  '本テーブルへの追加処理
  '------------------------------
    DataImport = True
  End If

End Function


の様な感じで、
・コマンドボタンをクリックしたら処理開始

・自作の処理、DataImportを呼び出す
 DataImportは成功の場合、Trueを、失敗の場合はFalseを返す

・返り値を判断して、Exitするかを決める

こんな感じでしょうか。


さて、重複のレコードがあるかの確認ですが、
クエリを作成する方法でいってみましょう。

クエリのSQLビューに下記SQLを貼り付けて
「Q_重複レコード」の名前で保存。

SELECT test.日付, test.社員番号
FROM test INNER JOIN W_ワークテーブル
ON (test.社員番号 = W_ワークテーブル.社員番号) AND
(test.日付 = W_ワークテーブル.日付);


SQLビューからの作り方が解らない場合は
h tp://www.vbalab.net/vbaqa/c-board.cgi?cmd=one;no=6726;id=access
(こちらの掲示板では直リンクが禁止ですので、補完して下さい)

この辺を参照して下さい。


このクエリが0件かどうかで判断をする事になりますが、
今回はとりあえずここまで^^

【9921】Re:インポート時の重複データ処理
質問  みう  - 07/10/11(木) 11:03 -

引用なし
パスワード
   ▼小僧 さん:

返信が遅れてすみません。。。

>・取引先のテーブル
>・W_ワークテーブル
>・今回インポートしたいデータの「CSVファイル」

えっと。。。
CSVファイルってあまりきちんと理解していないのですが、
Excelに2項目作ったデータのファイルのこともCSVファイルとなるのでしょうか?

>・コマンドボタンをクリックしたら処理開始
>↓
>・自作の処理、DataImportを呼び出す
> DataImportは成功の場合、Trueを、失敗の場合はFalseを返す
>↓
>・返り値を判断して、Exitするかを決める

流れが見えてきました!!
ありがとうございます!!


>さて、重複のレコードがあるかの確認ですが、
>クエリを作成する方法でいってみましょう。
>(中略)
>
>このクエリが0件かどうかで判断をする事になりますが、
>今回はとりあえずここまで^^


クエリも作成しました。どっちのテーブルにもあったら
クエリに内容表示っていうかんじですよね?
このクエリに1つでもはいっていたら、上書きするの?キャンセル?
っていうメッセージボックスを表示というかんじですね!!

ちょっとがんばってみます!!!

【9922】Re:インポート時の重複データ処理
質問  みう  - 07/10/11(木) 13:32 -

引用なし
パスワード
   ▼小僧 さん:

すみません。。。
つくっている途中でまたつまづきました。。。

クエリのなかにデータがあった場合、エラーなのはわかったのですが、
クエリを呼び出す(?)のはどうすればいいのでしょうか?

【9923】Re:インポート時の重複データ処理
回答  小僧  - 07/10/11(木) 15:09 -

引用なし
パスワード
   ▼みう さん:
こんにちは。

>>・今回インポートしたいデータの「CSVファイル」

>えっと。。。
>CSVファイルってあまりきちんと理解していないのですが、
>Excelに2項目作ったデータのファイルのこともCSVファイルとなるのでしょうか?

申し訳ありません。
Excelファイルでしたね…。


> クエリのなかにデータがあった場合、エラーなのはわかったのですが、
> クエリを呼び出す(?)のはどうすればいいのでしょうか?

クエリの中のレコード件数を確認するには
Recordset オブジェクトを使うのが一般的です。

こちらの掲示板で1から使い方を説明すると大変な量になってしまうので、
Web検索や参考書などで使い方を学んでください。
DAO と呼ばれるものと ADO と呼ばれるものがありますが、
Accessの中だけで使われるのでしたら DAO の方がより向いています。


また、件数を求めるだけでしたら定義域集計関数の DCount関数も有効です。
こちらですと

レコード数 = DCount("*","テーブル名またはクエリ名")

のような形で求める事ができます。

Function DataImport() As Boolean
Dim strSQL As String

'W_ワークテーブルの初期化
  strSQL = "DELETE FROM W_ワークテーブル"
  CurrentDb.Execute strSQL, dbFailOnError


'------------------------------------
'インポート処理
'------------------------------------

  If DCount("*", "Q_重複レコード") > 0 Then
    If MsgBox("処理を中止しますか?", vbCritical + vbYesNo) = vbYes Then
      DataImport = False
      Exit Function
    End If
  End If
  
  '------------------------------
  '本テーブルへの追加処理
  '------------------------------
  
  DataImport = True

End Function

【9924】Re:インポート時の重複データ処理
質問  みう  - 07/10/12(金) 11:52 -

引用なし
パスワード
   ▼小僧 さん:

おはようございます!

また、返信遅れすみません。。。。

クエリの件数をとることができました!
後、もう1つ教えていただきたいのですが、
最後の本テーブル(テーブル名「test」)にデータをインポートする際、
今のままですと、そのまま上書きせず、追加としてデータがインポートされてしまいます。
上書きしますか?と聞かれ、上書きしていいとオペレーション側がしたとき、
「test」テーブルに今回追加するデータをそまま丸々インポートするのはいいのですが・・・・

何か方法はありませんでしょうか?

何度も申し訳ないです。。。。

【9925】Re:インポート時の重複データ処理
回答  小僧  - 07/10/12(金) 18:36 -

引用なし
パスワード
   ▼みう さん:
こんにちは。

> 今のままですと、そのまま上書きせず、
> 追加としてデータがインポートされてしまいます。

具体的にコードを書きながら説明したいのですが、
ちょっと時間がないのでとりあえず方法だけでも…。


A) Q_重複レコード で表示されるものについては
  あらかじめ本番テーブル「test」から削除した後
  W_ワークテーブルの全レコードをインポートする


B) Q_重複レコード で表示されるものについて
  更新クエリを使って本番テーブル「test」を変更、
  重複しないものだけ W_ワークテーブルへ 追加の処理を行う


A) の方がプログラムを書く量が少なくてすみますが、
B) の方がデータベースとしてはスマートな処理になりますね。


また後ほどどんな内容のコードになるかを投稿しますね。

【9926】Re:インポート時の重複データ処理
回答  小僧  - 07/10/15(月) 10:06 -

引用なし
パスワード
   ▼みう さん:
こんにちは。

B) の方のコードです。
SQL(クエリ)を使って処理してみます。


まず、test にインデックスを張ります。
日付と社員番号で一意(Unique)になる様ですので

CREATE UNIQUE INDEX index1 ON test (日付, 社員番号);

上記をクエリにして実行されてみて下さい。

手動でつくる場合は hatena さんの詳しい説明がありますので
下記を参考にして下さい。

h tp://www.vbalab.net/vbaqa/c-board.cgi?cmd=one;no=9826;id=access


Function DataImport() As Boolean
Dim strSQL As String

'W_ワークテーブルの初期化
  strSQL = "DELETE FROM W_ワークテーブル"
  CurrentDb.Execute strSQL, dbFailOnError


'------------------------------------
'インポート処理
'------------------------------------

  If DCount("*", "Q_重複レコード") > 0 Then
    If MsgBox("重複データが見つかりました。" & vbCrLf _
    & "インポート処理を中止しますか?", "" _
    & vbCritical + vbYesNo) = vbYes Then
      DataImport = False
      Exit Function
    End If
  End If

'testテーブルの重複データ更新処理
  strSQL = "UPDATE test " _
      & "INNER JOIN W_ワークテーブル " _
      & "ON (test.日付 = W_ワークテーブル.日付) AND " _
       & "(test.社員番号 = W_ワークテーブル.社員番号) " _
     & "SET test.項目1 = W_ワークテーブル!項目1, " _
       & "test.項目2 = W_ワークテーブル!項目2;"
     
     '項目1、項目2の所は実際に更新したいフィールド名になります
     
  CurrentDb.Execute strSQL, dbFailOnError
     

'全データをtestテーブルに追加
'Index1 が張ってあれば、重複レコードはインポートされない
  strSQL = "INSERT INTO test( 日付, 社員番号, 項目1, 項目2 ) " _
      & "SELECT W_ワークテーブル.日付, " _
         & "W_ワークテーブル.社員番号, " _
         & "W_ワークテーブル.項目1, " _
         & "W_ワークテーブル.項目2 " _
      & "FROM W_ワークテーブル;"
  CurrentDb.Execute strSQL

  DataImport = True

End Function


項目1、項目2の所は
みうさんが実際にお使いのテーブルに合わせて下さい。

【9927】Re:インポート時の重複データ処理
お礼  みう  - 07/10/15(月) 16:04 -

引用なし
パスワード
   ▼小僧 さん:


お忙しい中、何日にもわたり教えていただいてくれてありがとうございます!!
無事解決いたしました!!

しかも丁寧に教えてもらったおかげで、わかりやすかったです。
小僧さん、ほんとうにありがとうございました!!

829 / 2272 ツリー ←次へ | 前へ→
ページ:  ┃  記事番号:
1078201
(SS)C-BOARD v3.8 is Free