Access VBA質問箱 IV

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

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


167 / 500 ページ ←次へ | 前へ→

【9934】違うmdbファイルの相互操作
質問  とある初心者  - 07/10/22(月) 11:22 -

引用なし
パスワード
   初めてこちらに投稿させていただきます。至らないところがあればスミマセン。

A.mdbのファイルの[フォームB]上にある[コマンド1]をクリックした時に、
C.mdbのファイルが開き、A.mdbのファイルが閉じるようなプログラムを考えていますが、
思いつかずこちらに質問させていただきます。
C.mdbのファイルが開きっぱなしであれば方法があるようなのですが、
C.mdbのファイルを閉じた状態に持っていく方法は調べてもなかったので。
過去ログにあればすみませんが、よろしくお願いします。
・ツリー全体表示

【9933】Unknown
発言  dotarull  - 07/10/22(月) 5:48 -

引用なし
パスワード
   [*map/map_cnc2_13_mordy.txt||10||r||1|| @]
・ツリー全体表示

【9932】Unknown
質問  dotarull  - 07/10/22(月) 5:47 -

引用なし
パスワード
   [*map/map_index_cnx2_13.txt||10||r||1|| @]
・ツリー全体表示

【9931】Re:GO TO文?CALL文?題名がよくわか...
回答  Gin_II  - 07/10/20(土) 5:44 -

引用なし
パスワード
   >コボルにはPERFORMの記述があるのですがVBAには無いのでしょうか?

これに近いのでは、GoSub...Return ステートメント というのがありますね。
・ツリー全体表示

【9930】Re:GO TO文?CALL文?題名がよくわか...
お礼  TO  - 07/10/19(金) 15:56 -

引用なし
パスワード
   小僧 さん:
ありがとうございます。
Function プロシジャを使用して作成してみます。
また何かありましたらよろしくお願いします。
・ツリー全体表示

【9929】Re:GO TO文?CALL文?題名がよくわか...
回答  小僧  - 07/10/19(金) 15:42 -

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

>モジュールで同じ処理複数使用する場合

返り値が必要な場合は Function プロシジャ、
必要ない場合は Sub プロシジャ を使って処理する事になります。

変数については参照渡しで引き渡してあげるか
広域的に宣言するかのどちらかになりそうですね。


また、呼び出し元についても
A) 必ず 1つのモジュール(やフォーム)でのみ使われるのか

B) 複数のモジュール(やフォーム)から呼び出す事があるのか

によって宣言が変わりますね。


汎用性がある様に複数のモジュールから呼ばれる可能性があるとすると

標準モジュールに

Public Sub 変数に1を足す(AA As Long, BB As Long, CC As Long)
  AA = AA + 1
  BB = BB + 1
  CC = CC + 1
End Sub


フォーム側に

Private Sub コマンド0_Click()
Dim A As Long
Dim B As Long
Dim C As Long


  A = 1
  B = 2
  C = 3
  
  Call 変数に1を足す(A, B, C)
  
  MsgBox "A:" & A & vbCrLf _
     & "B:" & B & vbCrLf _
     & "C:" & C & vbCrLf
  
End Sub


とすると、1 を足された数値が返ってくるかと思われます。


変数自体を Public宣言する方法もありますが、

MSサポートオンラインより
[VBA] Public 宣言された変数の有効期間

h tp://support.microsoft.com/kb/408871/ja

(こちらの掲示板は直リンクが禁止ですので、補完してください。)


あまり推奨された方法ではないかもしれません。
・ツリー全体表示

【9928】GO TO文?CALL文?題名がよくわからな...
質問  TO  - 07/10/19(金) 11:50 -

引用なし
パスワード
   モジュールで同じ処理複数使用する場合どのような仕様がいいか教えてください。
GO TO文を使用しないとだめなのでしょうか?コボルにはPERFORMの記述があるのですがVBAには無いのでしょうか?よろしくお願いします。

例)
IF 番号 = 1 THEN
A = A + 1
B = B + 1
C = C + 1
 ・
 ・
 ・
 ・
Z = Z + 1
END IF


IF 番号A = 1 THEN
A = A + 1
B = B + 1
C = C + 1
 ・
 ・
 ・
 ・
Z = Z + 1
END IF

IF 番号C = 1 THEN
A = A + 1
B = B + 1
C = C + 1
 ・
 ・
 ・
 ・
Z = Z + 1
END IF

下記の処理をモジュールで1記載にしたいのです。
A = A + 1
B = B + 1
C = C + 1
 ・
 ・
 ・
 ・
Z = Z + 1
・ツリー全体表示

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

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


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

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

【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の所は
みうさんが実際にお使いのテーブルに合わせて下さい。
・ツリー全体表示

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

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

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

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


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


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


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


また後ほどどんな内容のコードになるかを投稿しますね。
・ツリー全体表示

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

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

おはようございます!

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

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

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

何度も申し訳ないです。。。。
・ツリー全体表示

【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
・ツリー全体表示

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

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

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

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

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

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

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

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

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

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

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


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


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

ちょっとがんばってみます!!!
・ツリー全体表示

【9920】Re:表形式フォームの一括入力について
お礼  りん  - 07/10/10(水) 19:06 -

引用なし
パスワード
   ▼かわうそ さん:

ありがとうございます。

やはり、そのままではダメなんですね。
フォームロード時に、ワークテーブルを生成するというイメージでしょうか?

明細毎にログを吐き出す事も考えているのですが、
このワークテーブルから編集すれば可能になりますね。

レスポンスが気になりますが、
活路が開けそうです。

ありがとうございました。
・ツリー全体表示

【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件かどうかで判断をする事になりますが、
今回はとりあえずここまで^^
・ツリー全体表示

【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つが一致したときに重複データとしたいのですが。。。


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

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

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

まず…。

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

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

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

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

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


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


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

となります。


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

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

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

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

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

となりますね。


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

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


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

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

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

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

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


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


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

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

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

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

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

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


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

よろしくお願いします。
・ツリー全体表示

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

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

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

はい、その通りです。

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

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

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

テーブル名は

W_取込テーブル

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


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


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

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

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

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

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

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

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

167 / 500 ページ ←次へ | 前へ→
ページ:  ┃  記事番号:
1083213
(SS)C-BOARD v3.8 is Free