Access (VBA)

Access VBAに関するフォーラムです。
  • 解決済みのトピックにはコメントできません。
このトピックは解決済みです。
質問

 
(Windows 10全般 : Access 2016)
1つのデータ入力で複数のテーブルに入力することが出来るかどうか
投稿日時: 18/11/08 15:18:54
投稿者: Cst&Dog

現在CSVでデータを一括入力を行っています。
 
この入力を行うことで、顧客情報のテーブルと購入情報のテーブルの同じフィールド名に入力を行いたいと思っています。
 
こういったことは可能でしょうか?
 
また可能な場合、
顧客情報に重複するデータがあった際、データの選別が出来るよう重複データだけを別途表示させたりしたいと思います。
 
現在作ったCSV読み込みのVBAは下記になります。
 
----------------------------------------------------
 
Private Sub CSV書き出しボタン_Click()
      DoCmd.TransferText acExportDelim, , "M_顧客情報", "C:\Users\デスクトップ\Documents\アーカイブ\Accessアーカイブ顧客情報.csv", True
        MsgBox ("Accessアーカイブ顧客情報を書き出しました。")
End Sub
 
Private Sub CSV読み込みボタン_Click()
 
  Dim textData As String
  Dim fileNo As Long
  Dim myArray() As String
  Dim myRecordSet As Recordset
  Dim Input_Counter As Long
  Set myRecordSet = CurrentDb.OpenRecordset("M_顧客情報")
  fileNo = FreeFile
   
  Input_Counter = 0
  Open "C:\Users\デスクトップ\Documents\アーカイブ\Accessアーカイブ顧客情報.csv" For Input As #fileNo
  Line Input #fileNo, textData
   
  Do While Not EOF(fileNo)
   Line Input #fileNo, textData
   myArray = Split(textData, ",")
   myRecordSet.AddNew
     myRecordSet("注意事項") = Replace(myArray(1), """", "")
     myRecordSet("有無") = Replace(myArray(2), """", "")
     myRecordSet("名前") = Replace(myArray(3), """", "")
     myRecordSet("商品名") = Replace(myArray(4), """", "")
     myRecordSet("キャッシュバック") = Replace(myArray(5), """", "")
     myRecordSet("メールアドレス") = Replace(myArray(6), """", "")
     myRecordSet("メールアドレス2") = Replace(myArray(7), """", "")
     myRecordSet("メールアドレス3") = Replace(myArray(8), """", "")
     myRecordSet("金額") = Replace(myArray(9), """", "")
     myRecordSet("購入日") = Replace(myArray(10), """", "")
     myRecordSet("連絡日") = Replace(myArray(11), """", "")
     myRecordSet("日数") = Replace(myArray(12), """", "")
     myRecordSet("方法") = Replace(myArray(13), """", "")
     myRecordSet("備考") = Replace(myArray(14), """", "")
      
     myRecordSet.Update
Input_Counter = Input_Counter + 1
Me.取り込み件数 = Input_Counter
DoEvents
Loop
   
   Close #fileNo
   CSV追加結果.Requery
   myRecordSet.Close
   Set myRecordSet = Nothing
 
End Sub
----------------------------------------------------
ご教授いただけますと幸いです。
何卒宜しくお願い致します。

回答
投稿日時: 18/11/08 16:35:53
投稿者: sk

引用:
現在CSVでデータを一括入力を行っています。

引用:
DoCmd.TransferText acExportDelim, , "M_顧客情報", "C:\Users\デスクトップ\Documents\アーカイブ\Accessアーカイブ顧客情報.csv", True

引用:
Set myRecordSet = CurrentDb.OpenRecordset("M_顧客情報")

引用:
Open "C:\Users\デスクトップ\Documents\アーカイブ\Accessアーカイブ顧客情報.csv" For Input As #fileNo

引用:
myRecordSet.AddNew

テーブル[M_顧客情報]の全てのレコードを CSV ファイルにエクスポートして、
そのファイルを( Excel か何かのソフトで)編集してから、
再びテーブル[M_顧客情報]に追加するような作業をされているのですか?
 
引用:
この入力を行うことで、顧客情報のテーブルと購入情報のテーブルの
同じフィールド名に入力を行いたいと思っています。
  
こういったことは可能でしょうか?

各テーブルの構造(フィールドの名前/データ型、主キーの有無)や
リレーションシップの設定が不明ですので、今のところは何とも
お答えできません。
 
引用:
また可能な場合、
顧客情報に重複するデータがあった際、データの選別が出来るよう
重複データだけを別途表示させたりしたいと思います。

何のためになさっているか見当がつきませんが、
(厳密な意味では「顧客情報」ではない)テーブル[M_顧客情報]を
非正規形テーブルのまま取り扱っていることや、テーブルに
格納されている全てのレコードを CSV ファイルに出力して
同じテーブルに(上書きではなく)追加するような方式を
採られているのがそもそも良くないのではないか、というのが
今のところの印象。

投稿日時: 18/11/08 16:48:26
投稿者: Cst&Dog

分かりづらく申し訳ございません。
 
このデータは、別部署がGoogleのスプレットシートにまとめたものを私がいる部署で使用する際分かり易く検索できるようにするためのものです。
 
CSVでいれるのはスプレットシートのデータをAccess用に編集したものです。
毎月1回、データをまとめているのですがCSVで残るのは1ヶ月分ごとになるのでまとめたものが欲しいといわれたときに出せるよう【CSV書き出し】を設置しました。
 
 
リレーションシップは何も行っていません。
また、現在あるテーブルは顧客情報のみとなっています。
 
フィールド名は下記です。
注意事項
有無    
名前    
商品名    
キャッシュバック    
メールアドレス    
メールアドレス2    
メールアドレス3    
金額    
購入日    
連絡日    
日数    
方法    
備考
 
です。
 
ID以外は短いテキストになっておりIDはオートナンバー型です。
 
このようなものを行ってる理由ですが、もともとすべてスプレットシートで検索などをしていたのですが、データ量が多くなりすぎ検索にとても時間がかかっていました。
 
友人からAccessであれば早いと聞き、導入することになりました。
ただ、私が素人なので基本的にはネットにあるものをそのまま引用してきたりしてきたので、かなり無理矢理感はあります。
 
できるだけ検索にかかる時間を減らし、かつ、わかりやすいものを作りたいと思っています。
 
説明が下手で大変申し訳ございません。
何卒宜しくお願い致します。

回答
投稿日時: 18/11/08 18:15:09
投稿者: sk

引用:
このデータは、別部署がGoogleのスプレットシートにまとめたものを
私がいる部署で使用する際分かり易く検索できるようにするためのものです。

引用:
リレーションシップは何も行っていません。
また、現在あるテーブルは顧客情報のみとなっています。

つまり、CSV ファイルのインポート先である非正規形テーブル
(現在の[M_顧客情報])とは別に、本来の意味での[顧客マスタ]と
[購入履歴]に当たる正規形テーブルを作成なさろうとしているのでしょうか。
 
引用:
フィールド名は下記です。
注意事項
有無
名前
商品名
キャッシュバック
メールアドレス
メールアドレス2
メールアドレス3
金額
購入日
連絡日
日数
方法
備考

とりあえずやるべきことは、上記の非正規形テーブルから
「顧客の属性」を表すフィールドだけを抜き出して、
正規形テーブル[顧客マスタ]として集約することだと思います。

投稿日時: 18/11/08 18:48:32
投稿者: Cst&Dog

>>CSV ファイルのインポート先である非正規形テーブル
>>(現在の[M_顧客情報])とは別に、本来の意味での[顧客マスタ]と
>>[購入履歴]に当たる正規形テーブルを作成なさろうとしているのでしょうか。
 
そうです。
 
 
>>非正規形テーブルから
>>「顧客の属性」を表すフィールドだけを抜き出して、
>>正規形テーブル[顧客マスタ]として集約すること
 
これは、どういった形のものなのでしょうか?

回答
投稿日時: 18/11/09 10:48:44
投稿者: sk

引用:
>>非正規形テーブルから
>>「顧客の属性」を表すフィールドだけを抜き出して、
>>正規形テーブル[顧客マスタ]として集約すること
  
これは、どういった形のものなのでしょうか?

まず、[M_顧客情報](実際は購入履歴を表す記録)における
「顧客の属性」を表すフィールドを選別し、もし
同じ顧客のレコードが 2 件以上存在する場合、
それらのうちどのレコードの情報を参照すべきか、
という前提条件を考えなければなりません。
 
引用:
注意事項
有無
名前
商品名
キャッシュバック
メールアドレス
メールアドレス2
メールアドレス3
金額
購入日
連絡日
日数
方法
備考

引用:
ID以外は短いテキストになっておりIDはオートナンバー型です。

・[M_顧客情報]において、「顧客の属性」を表すフィールドは
 [名前],[メールアドレス],[メールアドレス2],[メールアドレス3]の
 4 つである。
 
・そのうち、個々の顧客を一意に識別するための
 値を持つフィールドは[名前]であると仮定する
 (値が Null であるレコードは存在しない)。
 なお、「名前が同じである他の顧客(別人)」、
 「購入時期によって名前が異なる顧客(改名)」、
 「名前の誤入力や表記揺れ、略称の使用」等に
 関しては、一切考慮しないものとする。
 
・それぞれの顧客の「最新の情報」として、
 [名前]ごとに「[ID]の値が最も大きいレコード」を
 抽出するようにする。
 なお、「最新の情報」に何らかの誤情報(あるいは情報不足)が
 含まれていたとしても、一切考慮しないものとする。
 
以上のような前提を仮定した場合は、例えば次のような
選択クエリを作成し、必要な情報だけを抜き出します。
 
( SQL ビュー)
---------------------------------------------------------
SELECT [M_顧客情報].[ID] AS [IDの最大],
       [M_顧客情報].[名前],
       [M_顧客情報].[メールアドレス],
       [M_顧客情報].[メールアドレス2],
       [M_顧客情報].[メールアドレス3]
FROM [M_顧客情報]
WHERE NOT EXISTS (SELECT tmp.*
                  FROM [M_顧客情報] tmp
                  WHERE tmp.[名前] = [M_顧客情報].[名前]
                    AND tmp.[ID] > [M_顧客情報].[ID])
ORDER BY [M_顧客情報].[ID];
---------------------------------------------------------
 
まずは上記のクエリの実行結果を元に、[顧客マスタ]に当たる
テーブルを新規作成してみると良いでしょう。

投稿日時: 18/11/09 12:23:19
投稿者: Cst&Dog

  

引用:

・そのうち、個々の顧客を一意に識別するための
 値を持つフィールドは[名前]であると仮定する
 (値が Null であるレコードは存在しない)。
 なお、「名前が同じである他の顧客(別人)」、
 「購入時期によって名前が異なる顧客(改名)」、
 「名前の誤入力や表記揺れ、略称の使用」等に
 関しては、一切考慮しないものとする。

 
これは名前が違うものはすべて別人として新しい顧客として表示されるという認識で間違いないでしょうか?
 
  
引用:

・それぞれの顧客の「最新の情報」として、
 [名前]ごとに「[ID]の値が最も大きいレコード」を
 抽出するようにする。
 なお、「最新の情報」に何らかの誤情報(あるいは情報不足)が
 含まれていたとしても、一切考慮しないものとする。

名前が同じでもメールアドレスが異なった場合追加や検証をすることは可能でしょうか?
メールアドレスを複数使用するお客様が多いため、メールアドレスが一致しない場合確認できると
とても助かります。
 

回答
投稿日時: 18/11/09 14:45:30
投稿者: sk

引用:
これは名前が違うものはすべて別人として
新しい顧客として表示されるという認識で間違いないでしょうか?

単純に[氏名]の値だけでそれぞれの顧客を
識別しようとするならば、そういうことになります。
 
仮に[氏名]ではなく[メールアドレス]の値を
顧客の識別に用いたとしても、やはり同様の問題が
起こり得るでしょう。
 
また、もし[氏名]や[メールアドレス]の入力が必須ではない
(値が Null であるレコードが含まれている)のであれば、
顧客識別のための ID として用いることが出来ない
(適さない)ケースが生じかねません。
 
引用:
名前が同じでもメールアドレスが異なった場合
追加や検証をすることは可能でしょうか?

例えば、次のようなユニオンクエリを作成することで、
それぞれの[氏名]と紐づいている全てのメールアドレスを
([メールアドレス2],[メールアドレス3]も含めて)
リストアップすることが出来ます。
 
( SQL ビュー)
----------------------------------------------------------
SELECT [M_顧客情報].[名前],
       [M_顧客情報].[メールアドレス]
FROM [M_顧客情報]
WHERE [M_顧客情報].[メールアドレス] Is Not Null
UNION
SELECT [M_顧客情報].[名前],
       [M_顧客情報].[メールアドレス2] AS [メールアドレス]
FROM [M_顧客情報]
WHERE [M_顧客情報].[メールアドレス2] Is Not Null
UNION
SELECT [M_顧客情報].[名前],
       [M_顧客情報].[メールアドレス3] AS [メールアドレス]
FROM [M_顧客情報]
WHERE [M_顧客情報].[メールアドレス3] Is Not Null
ORDER BY [名前],
         [メールアドレス];
----------------------------------------------------------
 
なお、[M_顧客情報]のレコードのうち、[メールアドレス],
[メールアドレス2], [メールアドレス3]の全ての値が
Null であるレコードは、上記のクエリの結果には含まれません。
(つまりメールアドレスの入力が省略されている顧客の
 データ検証には使用出来ない)
 
また、このクエリの実行結果を検証する場合は、
次のようなケースが含まれていることを
想定された方が良いでしょう。
 
・[氏名]の値が同じであっても、
 [メールアドレス]の値が異なる組み合わせがある。
 (同名の別人、メールアドレスの誤入力/複数入力/変更など)
 
・[メールアドレス]の値が同じであっても、
 [氏名]の値が異なる組み合わせがある。
 (改名、氏名の誤入力/表記揺れなど)
 
・それぞれの顧客が現在使用しているメールアドレスだけでなく、
 既に使用されなくなった過去のメールアドレスまで含まれている
 可能性がある。
 (それぞれのメールアドレスの有効性の是非)
 
以上の問題を踏まえた上で、先に例示した選択クエリの実行結果、
今回例示したユニオンクエリの結果などを比較、検討しながら、
( Access だけでなく、Excel を駆使するなどして)
正規の[顧客マスタ]として記録するレコードの内容を
整理する作業が必要となるでしょう。

投稿日時: 18/11/09 18:10:10
投稿者: Cst&Dog

 

引用:

( SQL ビュー)
----------------------------------------------------------
SELECT [M_顧客情報].[名前],
       [M_顧客情報].[メールアドレス]
FROM [M_顧客情報]
WHERE [M_顧客情報].[メールアドレス] Is Not Null
UNION
SELECT [M_顧客情報].[名前],
       [M_顧客情報].[メールアドレス2] AS [メールアドレス]
FROM [M_顧客情報]
WHERE [M_顧客情報].[メールアドレス2] Is Not Null
UNION
SELECT [M_顧客情報].[名前],
       [M_顧客情報].[メールアドレス3] AS [メールアドレス]
FROM [M_顧客情報]
WHERE [M_顧客情報].[メールアドレス3] Is Not Null
ORDER BY [名前],
         [メールアドレス];
----------------------------------------------------------

 
こちらを使用した際、すべてのデータで
名前 アドレス
顧客名1
顧客名1 アドレス
顧客名2
顧客名2 アドレス
顧客名3
顧客名3 アドレス1
顧客名3 アドレス2
 
といった表記になったのですが、顧客名3の部分だけ表示することは難しいでしょうか?
また、こちらのクエリを使用した際テーブルに出来なかったのですが、これは正しい挙動でしょうか?
 
分からないことが多く、質問ばかりですみません。
何卒宜しくお願い致します。

回答
投稿日時: 18/11/09 21:39:20
投稿者: sk

引用:
myRecordSet("メールアドレス") = Replace(myArray(6), """", "")
myRecordSet("メールアドレス2") = Replace(myArray(7), """", "")
myRecordSet("メールアドレス3") = Replace(myArray(8), """", "")

そういえば、CSV ファイル上において値が入力されていない列に関しては、
Null ではなく空文字列を代入されていましたね。
 
引用:
こちらのクエリを使用した際テーブルに出来なかったのですが、
これは正しい挙動でしょうか?

1. 以下のユニオンクエリを新規作成し、
   [Q_顧客メールアドレス抽出]という名前を付けて保存する。
 
( SQL ビュー)
-----------------------------------------------------------
SELECT [M_顧客情報].[名前],
       [M_顧客情報].[メールアドレス]
FROM [M_顧客情報]
WHERE Nz([M_顧客情報].[メールアドレス],"") <> ""
UNION
SELECT [M_顧客情報].[名前],
       [M_顧客情報].[メールアドレス2] AS [メールアドレス]
FROM [M_顧客情報]
WHERE Nz([M_顧客情報].[メールアドレス2],"") <> ""
UNION
SELECT [M_顧客情報].[名前],
       [M_顧客情報].[メールアドレス3] AS [メールアドレス]
FROM [M_顧客情報]
WHERE Nz([M_顧客情報].[メールアドレス3],"") <> ""
ORDER BY [名前],
         [メールアドレス];
-----------------------------------------------------------
 
2. 以下のテーブル作成クエリを実行し、
   テーブル[T_顧客メールアドレス一覧]を作成する。
 
( SQL ビュー)
-----------------------------------------------------------
SELECT [Q_顧客メールアドレス抽出].[名前],
       [Q_顧客メールアドレス抽出].[メールアドレス]
INTO [T_顧客メールアドレス一覧]
FROM [Q_顧客メールアドレス抽出]
ORDER BY [Q_顧客メールアドレス抽出].[名前],
         [Q_顧客メールアドレス抽出].[メールアドレス];
-----------------------------------------------------------
 
引用:
顧客名3の部分だけ表示することは難しいでしょうか?

3. 以下の選択クエリを新規作成し、[Q_複数メールアドレス保有候補]
   という名前を付けて保存する。
 
( SQL ビュー)
----------------------------------------------------------------
SELECT [T_顧客メールアドレス一覧].[名前],
       [T_顧客メールアドレス一覧].[メールアドレス]
FROM [T_顧客メールアドレス一覧]
WHERE (SELECT Count(*)
       FROM [T_顧客メールアドレス一覧] tmp
       WHERE tmp.[名前] = [T_顧客メールアドレス一覧].[名前]) > 1
ORDER BY [T_顧客メールアドレス一覧].[名前],
         [T_顧客メールアドレス一覧].[メールアドレス];
----------------------------------------------------------------
 
4. 以下の選択クエリを新規作成し、
   [Q_改名候補]という名前を付けて保存する。
 
( SQL ビュー)
----------------------------------------------------------------
SELECT [T_顧客メールアドレス一覧].[メールアドレス],
       [T_顧客メールアドレス一覧].[名前]
FROM [T_顧客メールアドレス一覧]
WHERE (SELECT Count(*)
       FROM [T_顧客メールアドレス一覧] tmp
       WHERE tmp.[メールアドレス] = [T_顧客メールアドレス一覧].[メールアドレス]) > 1
ORDER BY [T_顧客メールアドレス一覧].[メールアドレス],
         [T_顧客メールアドレス一覧].[名前];
----------------------------------------------------------------
 
上記 1 〜 4 の操作を行なった上、[Q_複数メールアドレス保有候補]と
[Q_改名候補]の実行結果をそれぞれ検証してみて下さい。

投稿日時: 18/11/10 00:24:37
投稿者: Cst&Dog

1〜4を作成しアドレスが同じで名前が違う【改名候補】と
名前が同じでアドレスが複数ある【Q_顧客メールアドレス抽出】を
出すことが出来ました!!
 
これを統合させたり、残したりする場合は各クエリ上で編集するのでしょうか?
 
また、出てきたデータを見て名前も一部残しておきたいと思ったのですが、名前の欄を1つ増やすことは可能でしょうか?
 
何卒宜しくお願い致します。

回答
投稿日時: 18/11/12 09:46:44
投稿者: sk

引用:
これを統合させたり、残したりする場合は
各クエリ上で編集するのでしょうか?

・[Q_顧客メールアドレス抽出]を元にしたテーブル作成クエリによって
 テーブル[T_顧客メールアドレス一覧]を作成したのと同様に、
 [Q_複数メールアドレス保有候補]や[Q_改名候補]を元に
 新規テーブルを作成し、それらのテーブルを作業用テーブル
 として編集する。
 
・[Q_複数メールアドレス保有候補]や[Q_改名候補]を
 Excel ワークシートとしてエクスポートし、
 それらのワークシートを作業用シートとして編集する。
 (編集後、そのワークシートを accdb ファイルにインポートし直す)
 
など、やりやすいと思う方法でどうぞ。
 
引用:
また、出てきたデータを見て名前も一部残しておきたいと思ったのですが、
名前の欄を1つ増やすことは可能でしょうか?

作業用テーブルを作成されるなら、そのテーブルをデザインビューで開いて
新しいフィールド(テキスト型)を追加なさればよいでしょうし、
Excel にエクスポートされるのであれば、エクスポートされた
ワークシートに新たな列(文字列形式)を追加なさればよろしいでしょう。
 
いずれにせよ、最終的には[氏名]や[メールアドレス]とは別に
[顧客ID]に当たるフィールドを設ける方向で進められた方がよいと思います。

投稿日時: 18/11/12 13:08:22
投稿者: Cst&Dog

元のデータに顧客IDを付けることができないので、Accessにインポートした際にオートでつくものをIDとして管理していきたいと思います。
 
また、教えて頂きました通りにテーブルにし、EXCELで編集しようと思います。
 
上記のものを顧客基本情報にし、購入情報をどんどん足していこうと思うのですが、その場合、今までどおりのCSVでインポートしてきた場合、顧客基本情報とどのように紐づけすることができますか?

回答
投稿日時: 18/11/12 15:44:15
投稿者: sk

引用:
上記のものを顧客基本情報にし、購入情報をどんどん足していこうと思うのですが、
その場合、今までどおりのCSVでインポートしてきた場合、顧客基本情報と
どのように紐づけすることができますか?

・CSV ファイル側において、それぞれの顧客を
 どのようにして識別/区別するのか。
 (現時点では[氏名]と[メールアドレス]で判断するしかないが、
 どちらを用いても 100 パーセントの精度は保証されない)
 
・テーブル[顧客基本情報]が最終的にどのような構造となるか。
 
・どの段階までの作業ならば自動化することが可能か。
 
・手動でのデータ編集作業がどの段階で、
 どのような形で介入することになるのか。
 
・手動でのデータ編集の結果をどのようにして
 [顧客基本情報]のレコードとして反映させるのか。
 (レコードの追加/更新/削除)
 
といった問題を詳細に検討する必要がありますので
(そしてそれは、CSV ファイルの中身を直接見ることが
出来る人が精査しながら判断すべきですので)、
一つ一つの作業の流れについて、具体的な方法や
操作手順等をこちらから示すことは出来ません。
 
例えば単純に、テーブル[T_顧客メールアドレス一覧]に
格納されていない[氏名]と[メールアドレス]の組み合わせを、
[T_顧客メールアドレス一覧]の新規レコードとして追加する
といった場合は、次のような追加クエリをあらかじめ作成しておき
(仮に[Q_顧客メールアドレス差分追加]という名前で保存し)、
CSV ファイルのインポートが実行されてから、そのクエリを
実行するようになさればよいでしょう。
 
( SQL ビュー)
----------------------------------------------------------
INSERT INTO [T_顧客メールアドレス一覧] 
      ([名前], 
       [メールアドレス])
SELECT [Q_顧客メールアドレス抽出].[名前], 
       [Q_顧客メールアドレス抽出].[メールアドレス]
FROM [Q_顧客メールアドレス抽出] 
LEFT JOIN [T_顧客メールアドレス一覧] 
ON  [Q_顧客メールアドレス抽出].[名前] = [T_顧客メールアドレス一覧].[名前] 
AND [Q_顧客メールアドレス抽出].[メールアドレス] = [T_顧客メールアドレス一覧].[メールアドレス] 
WHERE [T_顧客メールアドレス一覧].[メールアドレス] Is Null 
ORDER BY [Q_顧客メールアドレス抽出].[名前], 
         [Q_顧客メールアドレス抽出].[メールアドレス];
----------------------------------------------------------
 
ただ、そのままではそれぞれのレコードがいつテーブルに
追加されたのかが判りませんので、[T_顧客メールアドレス一覧]に
[登録日時]という日付/時刻型のフィールドを新たに追加しておき、
新規レコードを追加する際に[登録日時]に Now 関数の戻り値が
代入されるようにする、といった工夫が必要となるでしょう。

投稿日時: 18/11/13 14:37:08
投稿者: Cst&Dog

 

引用:

・CSV ファイル側において、それぞれの顧客を
 どのようにして識別/区別するのか。
 (現時点では[氏名]と[メールアドレス]で判断するしかないが、
 どちらを用いても 100 パーセントの精度は保証されない)

名前とメアドでの識別で分かる範囲で行おうと思っています。
  
 
 
引用:

・テーブル[顧客基本情報]が最終的にどのような構造となるか。

出来れば、
名前
メアド
メアド2
メアド3
電話番号
電話番号2
電話番号3
住所…
のようなものになればと思っています…。
 
 
 
引用:

・どの段階までの作業ならば自動化することが可能か。

CSVにまとめるところまでは手動でしようと思っています。
CSVでインポートしてそれを顧客情報と購入情報にいれ、かつ重複の確認や統合の確認部分まで自動となるのが一番理想ではありますが、これは難しいのかなとは思っています。
  
 
 
引用:

・手動でのデータ編集作業がどの段階で、
 どのような形で介入することになるのか。

CSVにまとめる部分は手動で行います。
また、CSVに入っていない顧客情報は手動で足していこうと思っています。
 
 
 
引用:

・手動でのデータ編集の結果をどのようにして
 [顧客基本情報]のレコードとして反映させるのか。
 (レコードの追加/更新/削除)

レコードに直打ちかとは思っていました。
 
 
また、可能であればですが、現在のCSV一括入力の保存先を現在は1つのテーブルですが、顧客情報、購入情報両方に入力することは可能でしょうか?
考えていたのが、CSVとしては
 
名前、メアド、メアド2、メアド2、メアド3、商品名、購入日
 
などにして、CSV読み込みの時に
顧客情報には名前、メアド、メアド2、メアド2、メアド3
購入情報には名前、商品名、購入日
に分けれれば同時に同じIDを割り当てれるのでは…と思うのですがいかかでしょうか?
 

回答
投稿日時: 18/11/14 11:09:33
投稿者: sk

引用:
CSV読み込みの時に
顧客情報には名前、メアド、メアド2、メアド2、メアド3
購入情報には名前、商品名、購入日
に分けれれば同時に同じIDを割り当てれるのでは…
と思うのですがいかかでしょうか?

(以下、P は主キー)
 
[TW_顧客基本情報]
-----------------------------------------------------
P 顧客ID            長整数型
  名前              テキスト型
  メールアドレス    テキスト型
  メールアドレス2   テキスト型
  メールアドレス3   テキスト型
  登録日時          日付/時刻型
-----------------------------------------------------
 
[TW_購入履歴]
-----------------------------------------------------
P 購入履歴ID        長整数型
  顧客ID            長整数型
  購入時顧客名      テキスト型
  購入日            日付/時刻型
  商品名            テキスト型
  金額              通貨型
  登録日時          日付/時刻型
-----------------------------------------------------
 
以上のような作業用テーブルをあらかじめ定義しておき、
[M_顧客情報]のレコードを上記の各テーブルのレコードに
変換する場合は、次のようなコードを実行なさればよいでしょう。
 
 
(標準モジュール)
-----------------------------------------------------
Option Compare Database
Option Explicit
 
Private Const SourceTableName As String = "M_顧客情報"
Private Const CustomersWorkTableName As String = "TW_顧客基本情報"
Private Const PurchaseWorkTableName As String = "TW_購入履歴"
 
Public Sub subCreateWorkRecords()
     
    Dim db As DAO.Database
    Dim rsSource As DAO.Recordset
    Dim rsCustomers As DAO.Recordset
     
    Dim strSQL As String
    Dim strInsertSQL As String
    Dim strSelectSQL As String
    Dim strFromSQL As String
    Dim strWhereSQL As String
    Dim strGroupSQL As String
    Dim strOrderSQL As String
     
    Dim lngNewCustomerID As Long
    Dim dtCurrentTime As Date
     
    Set db = CurrentDb
     
    strSQL = "DELETE * FROM [" & CustomersWorkTableName & "]"
    db.Execute strSQL, dbFailOnError
     
    strSQL = "DELETE * FROM [" & PurchaseWorkTableName & "]"
    db.Execute strSQL, dbFailOnError
     
    strSelectSQL = " SELECT t1.[名前]" & _
                   ", t1.[メールアドレス]" & _
                   ", t1.[メールアドレス2]" & _
                   ", t1.[メールアドレス3]"
     
    strFromSQL = " FROM [" & SourceTableName & "] t1"
     
    strWhereSQL = " WHERE Nz(t1.[名前],'')<>''"
     
    strGroupSQL = " GROUP BY t1.[名前]" & _
                  ", t1.[メールアドレス]" & _
                  ", t1.[メールアドレス2]" & _
                  ", t1.[メールアドレス3]"
     
    strOrderSQL = " ORDER BY Min(t1.[ID])"
     
    strSQL = strSelectSQL & _
             strFromSQL & _
             strWhereSQL & _
             strGroupSQL & _
             strOrderSQL
     
    Set rsSource = db.OpenRecordset(strSQL, dbOpenSnapshot)
     
    Set rsCustomers = db.OpenRecordset(CustomersWorkTableName, dbOpenDynaset)
     
    lngNewCustomerID = 0
    dtCurrentTime = Now()
     
    With rsSource
        Do Until .EOF
            lngNewCustomerID = lngNewCustomerID + 1
            rsCustomers.AddNew
            rsCustomers![顧客ID] = lngNewCustomerID
            rsCustomers![名前] = ![名前]
            rsCustomers![メールアドレス] = ![メールアドレス]
            rsCustomers![メールアドレス2] = ![メールアドレス2]
            rsCustomers![メールアドレス3] = ![メールアドレス3]
            rsCustomers![登録日時] = dtCurrentTime
            rsCustomers.Update
             
            strInsertSQL = "INSERT INTO [" & PurchaseWorkTableName & "] ("
             
            strInsertSQL = strInsertSQL & _
                           " [購入履歴ID]" & _
                           ", [顧客ID]" & _
                           ", [購入時顧客名]" & _
                           ", [購入日]" & _
                           ", [商品名]" & _
                           ", [金額]" & _
                           ", [登録日時]"
             
            strInsertSQL = strInsertSQL & ") "
             
            strSelectSQL = " SELECT " & _
                           " t1.[ID]" & _
                           ", " & lngNewCustomerID & " AS [顧客ID]" & _
                           ", t1.[名前]" & _
                           ", IIf(IsDate(t1.[購入日]),CDate(t1.[購入日]),Null) AS [購入日]" & _
                           ", t1.[商品名]" & _
                           ", IIf(IsNumeric(t1.[金額]),CCur(t1.[金額]),Null) AS [金額]" & _
                           ", #" & Format(dtCurrentTime, "yyyy/mm/dd hh:nn:ss") & "# AS [登録日時]"
             
            strFromSQL = " FROM [" & SourceTableName & "] t1"
             
            strWhereSQL = " WHERE Nz(t1.[名前],'') = '" & ![名前] & "'" & _
                          " AND Nz(t1.[メールアドレス],'') = '" & ![メールアドレス] & "'" & _
                          " AND Nz(t1.[メールアドレス2],'') = '" & ![メールアドレス2] & "'" & _
                          " AND Nz(t1.[メールアドレス3],'') = '" & ![メールアドレス3] & "'"
             
            strOrderSQL = " ORDER BY t1.[ID]"
             
            strSQL = strInsertSQL & _
                     strSelectSQL & _
                     strFromSQL & _
                     strWhereSQL & _
                     strOrderSQL
 
            db.Execute strSQL, dbFailOnError
 
            .MoveNext
        Loop
    End With
 
    Set rsCustomers = Nothing
    Set rsSource = Nothing
    Set db = Nothing
     
    MsgBox "作業用テーブルにレコードを追加しました。", _
           vbInformation, _
           "実行完了(subCreateWorkRecords)"
     
End Sub
-----------------------------------------------------
 
なお、上記のサンプルコードによって自動生成される
[顧客ID]の値は、あくまで編集作業のための
仮の ID に過ぎません。

投稿日時: 18/11/16 12:39:51
投稿者: Cst&Dog

教えていただきましたコードで2つのテーブルにデータを入れることが出来ました!!
ありがとうございます。
 
購入履歴の項目を増やしたいのですが、テーブルの項目をを増やした後、どの位置のコードに足せばいいでしょうか?
 
ご教授何卒宜しくお願い致します。

回答
投稿日時: 18/11/16 17:00:23
投稿者: sk

引用:
購入履歴の項目を増やしたいのですが、
テーブルの項目をを増やした後、
どの位置のコードに足せばいいでしょうか?

引用:
            strInsertSQL = "INSERT INTO [" & PurchaseWorkTableName & "] ("
             
            strInsertSQL = strInsertSQL & _
                           " [購入履歴ID]" & _
                           ", [顧客ID]" & _
                           ", [購入時顧客名]" & _
                           ", [購入日]" & _
                           ", [商品名]" & _
                           ", [金額]" & _
                           ", [登録日時]"
             
            strInsertSQL = strInsertSQL & ") "

            strInsertSQL = "INSERT INTO [" & PurchaseWorkTableName & "] ("
              
            strInsertSQL = strInsertSQL & _
                           " [購入履歴ID]" & _
                           ", [顧客ID]" & _
                           ", [購入時顧客名]" & _
                           ", [購入日]" & _
                           ", [商品名]" & _
                           ", [金額]" & _
                           ", [登録日時]"
 
            strInsertSQL = strInsertSQL & _
                           ", [追加したフィールドの名前1]" & _
                           ", [追加したフィールドの名前2]" & _
                           ", [追加したフィールドの名前3]"
 
            strInsertSQL = strInsertSQL & ") "
 
引用:
            strSelectSQL = " SELECT " & _
                           " t1.[ID]" & _
                           ", " & lngNewCustomerID & " AS [顧客ID]" & _
                           ", t1.[名前]" & _
                           ", IIf(IsDate(t1.[購入日]),CDate(t1.[購入日]),Null) AS [購入日]" & _
                           ", t1.[商品名]" & _
                           ", IIf(IsNumeric(t1.[金額]),CCur(t1.[金額]),Null) AS [金額]" & _
                           ", #" & Format(dtCurrentTime, "yyyy/mm/dd hh:nn:ss") & "# AS [登録日時]"

            strSelectSQL = " SELECT " & _
                           " t1.[ID]" & _
                           ", " & lngNewCustomerID & " AS [顧客ID]" & _
                           ", t1.[名前]" & _
                           ", IIf(IsDate(t1.[購入日]),CDate(t1.[購入日]),Null) AS [購入日]" & _
                           ", t1.[商品名]" & _
                           ", IIf(IsNumeric(t1.[金額]),CCur(t1.[金額]),Null) AS [金額]" & _
                           ", #" & Format(dtCurrentTime, "yyyy/mm/dd hh:nn:ss") & "# AS [登録日時]"
            strSelectSQL = strSelectSQL & _
                           ", t1.[値を代入したいフィールドの名前1]" & _
                           ", t1.[値を代入したいフィールドの名前2]" & _
                           ", t1.[値を代入したいフィールドの名前3]"
 
------------------------------------------------------------------
 
3 つ足される場合は以上のような感じでどうぞ。
 
代入先となる[TW_購入履歴]のフィールドと、
代入元となる[M_顧客情報]のフィールド(または式)の、
数と順番、それぞれのデータ型が一致するようにして下さい。

投稿日時: 18/11/19 20:39:26
投稿者: Cst&Dog

ご返信が遅くなり申し訳ございません。
 
下記のように変更したのですが、エラーがでてしまいました。
 
実行時エラー'3061':
パラメーターが少なすぎます。2を指定してください。
 
どこを訂正すればいいでしょうか?
度々となり申し訳ございませんが何卒宜しくお願い致します。
 
 

引用:

Option Compare Database
Option Explicit
  
Private Const SourceTableName As String = "M_顧客情報"
Private Const CustomersWorkTableName As String = "TW_顧客基本情報"
Private Const PurchaseWorkTableName As String = "TW_購入履歴"
  
 
Public Sub subCreateWorkRecords()
      
    Dim db As DAO.Database
    Dim rsSource As DAO.Recordset
    Dim rsCustomers As DAO.Recordset
      
    Dim strSQL As String
    Dim strInsertSQL As String
    Dim strSelectSQL As String
    Dim strFromSQL As String
    Dim strWhereSQL As String
    Dim strGroupSQL As String
    Dim strOrderSQL As String
      
    Dim lngNewCustomerID As Long
    Dim dtCurrentTime As Date
      
    Set db = CurrentDb
      
    strSQL = "DELETE * FROM [" & CustomersWorkTableName & "]"
    db.Execute strSQL, dbFailOnError
      
    strSQL = "DELETE * FROM [" & PurchaseWorkTableName & "]"
    db.Execute strSQL, dbFailOnError
      
    strSelectSQL = " SELECT t1.[名前]" & _
                   ", t1.[メールアドレス]" & _
                   ", t1.[メールアドレス2]" & _
                   ", t1.[メールアドレス3]"
      
    strFromSQL = " FROM [" & SourceTableName & "] t1"
      
    strWhereSQL = " WHERE Nz(t1.[名前],'')<>''"
      
    strGroupSQL = " GROUP BY t1.[名前]" & _
                  ", t1.[メールアドレス]" & _
                  ", t1.[メールアドレス2]" & _
                  ", t1.[メールアドレス3]"
      
    strOrderSQL = " ORDER BY Min(t1.[ID])"
      
    strSQL = strSelectSQL & _
             strFromSQL & _
             strWhereSQL & _
             strGroupSQL & _
             strOrderSQL
      
    Set rsSource = db.OpenRecordset(strSQL, dbOpenSnapshot)
      
    Set rsCustomers = db.OpenRecordset(CustomersWorkTableName, dbOpenDynaset)
      
    lngNewCustomerID = 0
    dtCurrentTime = Now()
      
    With rsSource
        Do Until .EOF
            lngNewCustomerID = lngNewCustomerID + 1
            rsCustomers.AddNew
            rsCustomers![顧客ID] = lngNewCustomerID
            rsCustomers![名前] = ![名前]
            rsCustomers![メールアドレス] = ![メールアドレス]
            rsCustomers![メールアドレス2] = ![メールアドレス2]
            rsCustomers![メールアドレス3] = ![メールアドレス3]
            rsCustomers![登録日時] = dtCurrentTime
            rsCustomers.Update
              
             strInsertSQL = "INSERT INTO [" & PurchaseWorkTableName & "] ("
               
            strInsertSQL = strInsertSQL & _
                           " [購入履歴ID]" & _
                           ", [顧客ID]" & _
                           ", [購入時顧客名]" & _
                           ", [購入日]" & _
                           ", [商品名]" & _
                           ", [金額]" & _
                           ", [登録日時]"
  
            strInsertSQL = strInsertSQL & _
                           ", [キャッシュバック]" & _
                           ", [連絡日]" & _
                           ", [入金方法]"
  
            strInsertSQL = strInsertSQL & ") "
              
            strSelectSQL = " SELECT " & _
                           " t1.[ID]" & _
                           ", " & lngNewCustomerID & " AS [顧客ID]" & _
                           ", t1.[名前]" & _
                           ", IIf(IsDate(t1.[購入日]),CDate(t1.[購入日]),Null) AS [購入日]" & _
                           ", t1.[商品名]" & _
                           ", IIf(IsNumeric(t1.[金額]),CCur(t1.[金額]),Null) AS [金額]" & _
                           ", #" & Format(dtCurrentTime, "yyyy/mm/dd hh:nn:ss") & "# AS [登録日時]"
                            
            strSelectSQL = strSelectSQL & _
                           ", t1.[キャッシュバック]" & _
                           ", t1.[連絡日]" & _
                           ", t1.[入金方法]"
 
              
            strFromSQL = " FROM [" & SourceTableName & "] t1"
              
            strWhereSQL = " WHERE Nz(t1.[名前],'') = '" & ![名前] & "'" & _
                          " AND Nz(t1.[メールアドレス],'') = '" & ![メールアドレス] & "'" & _
                          " AND Nz(t1.[メールアドレス2],'') = '" & ![メールアドレス2] & "'" & _
                          " AND Nz(t1.[メールアドレス3],'') = '" & ![メールアドレス3] & "'"
              
            strOrderSQL = " ORDER BY t1.[ID]"
              
            strSQL = strInsertSQL & _
                     strSelectSQL & _
                     strFromSQL & _
                     strWhereSQL & _
                     strOrderSQL
  
            db.Execute strSQL, dbFailOnError
  
            .MoveNext
        Loop
    End With
  
    Set rsCustomers = Nothing
    Set rsSource = Nothing
    Set db = Nothing
      
    MsgBox "作業用テーブルにレコードを追加しました。", _
           vbInformation, _
           "実行完了(subCreateWorkRecords)"
      
End Sub
 
 

回答
投稿日時: 18/11/20 09:50:05
投稿者: sk

引用:
下記のように変更したのですが、エラーがでてしまいました。
  
実行時エラー'3061':
パラメーターが少なすぎます。2を指定してください。

[M_顧客情報]のフィールド名の指定を間違えている箇所が
2 つほどあるのだと思います。
 
引用:
myRecordSet("キャッシュバック") = Replace(myArray(5), """", "")

引用:
myRecordSet("連絡日") = Replace(myArray(11), """", "")

引用:
myRecordSet("方法") = Replace(myArray(13), """", "")

引用:
フィールド名は下記です。
注意事項
有無
名前
商品名
キャッシュバック
メールアドレス
メールアドレス2
メールアドレス3
金額
購入日
連絡日
日数
方法
備考
  
です

引用:
strSelectSQL = strSelectSQL & _
               ", t1.[キャッシュバック]" & _
               ", t1.[連絡日]" & _
               ", t1.[入金方法]"

少なくとも、[入金方法]という名前のフィールドは
[M_顧客情報]には存在しないはずです。
 
もう 1 箇所の方については、例えばいずれかのフィールドの名前を
変更したとか、そういうことではないかと。
 
引用:
strInsertSQL = strInsertSQL & _
               ", [キャッシュバック]" & _
               ", [連絡日]" & _
               ", [入金方法]"

また、[TW_購入履歴]に追加されたフィールドの
名前に関しても再度ご確認されることをお奨めします。

投稿日時: 18/11/21 09:11:08
投稿者: Cst&Dog

何度もコードを組んで頂きありがとうございます!
無事、思っていたものとなりました。
 
また、別内容で質問を出すかと思いますが、その際はまたご教授頂けますととても助かります。
 
本当にありがとうございました。