マンガでよめる痔のこと・薬のこと

ACCESSのサブフォームコピーについて

お世話になります。色々検索してたのですがなかなか解決できず、教えて下さい。

下記のようなフォームがあります。
メインフォームにボタンを設置し、メインフォームとサブフォームを同時にコピーしたいです。

【メインフォーム】
ID(オートナンバー)
登録名
住所
電話番号
など

【サブフォーム】
SubID(オートナンバー)
ID(メインフォームと連結)
ライセンス数
開始日
など

メインフォームの「内容のコピーを作成」ボタンのクリック時の[イベント プロシージャ]に下記が記載してあります。
---
Private Sub 内容のコピーを作成_Click()
On Error GoTo Err_内容のコピーを作成_Click

Select Case MsgBox(srchXls & "◆内容のコピーを作成しますか?◆", vbOKCancel)
Case vbOK

DoCmd.DoMenuItem acFormBar, acEditMenu, 8, , acMenuVer70
DoCmd.DoMenuItem acFormBar, acEditMenu, 2, , acMenuVer70
DoCmd.DoMenuItem acFormBar, acEditMenu, 5, , acMenuVer70 'Paste Append

MsgBox (srchXls & Chr(13) & Chr(10) & "◆コピーを作成しました◆")

Err_内容のコピーを作成_Click:

Case Else
Exit Sub
End Select
End Sub
---

これではメインフォームのコピーしか出来ません。
サブフォームも一緒にコピーしたいのですが、どういった方法があるでしょうか。

宜しくお願いいたします。

このQ&Aに関連する最新のQ&A

A 回答 (17件中1~10件)

No.16です。



> 念のためテストデータで検証後に本データに反映させますので、
> 数日のタイムラグはありますので大丈夫です(^^)

とりあえず、それを聞いて安心しました。


・・・さて、以下の件ですが、

> フォーカスはサブフォームのレコードを貼り付けたところで止まっています。

前回回答した「フォーカス移動の対応」を入れる前にはエラーが
なかったことから考えても、改修部分での発生と思います。

とりあえず、思いつくパターンをこちらのサンプルで確認したところ
 a)「Me!」の直後の部分(IDやサブフォーム名)を、実際にはない
  「ID1」などにした場合:
  「2465」の当該フィールドがないとのエラー
 b)「Me.」の直後の部分(GotoPage)に、実際にはない「GotoPageA」
  などを指定した場合:
  コマンドボタンを押した直後にコンパイルエラー
 c)「Me!」の後に続いて、「.」で始まる「SetFocus」や「SourceObject」
  を、それぞれ「SetFocus1」や「SourceObject1」にした場合:
  「438」のサポートしていないとのエラー
という結果になりましたので、「c」の部分のスペルミスの可能性が
高いように思います。

・・・IDやサブフォームがコントロールであることをわかりやすくする
意味で、先頭に「Me!」をつけたのですが、実際には「Me!」はなくても
正しく動作します。
ですので、両者(IDとサブフォーム名)の「Me!」を削除(Deleteキーで
消去)した上で、コード表示画面のメニューから、「デバッグ(D)→
○○のコンパイル(L)」をクリックしてみてください。
「コンパイルエラー」のメッセージを『OK』をクリックして閉じると、
間違いがあった部分が反転表示されますので、そこが修正が必要な箇所
ということになります。
(「.SetFocus」「.SourceObject」の部分を削除後、IDやサブフォーム名
 の後ろに半角ピリオド「.」を入力すると、指定できるパラメータの候補
 が表示されるので、そこから選ぶのが一番確実です:
 予め「Me!」を削除しておかないと、この機能は働かないのでご注意を)


・・・もしも上記とは別のところでエラーが発生していた場合は、
そこに対して、同様の手順を試してみてください。
また、上の方法でコンパイルエラーが発生しなかった場合は、
コード冒頭の「On Error Goto エラー処理」の先頭に「'」を追加
して、独自のエラー処理を無効化してから、再度コピー処理を
実行してみてください。
(エラーメッセージに『デバッグ』というボタンが表示されるので、
 それをクリックすると、エラー箇所が黄色表示されます)
※メニューから「実行(R)→リセット(R)」を選択するか、ツール
 バーのリセットボタン(青い四角形)を押して黄色表示を解除
 した後、その行を改修します。

なお、もしもVBAに表示制限用のパスワードを設定している
場合は、予めパスワードを通しておかないと、エラーメッセージ
の『デバッグ』ボタンは押せないので、ご注意下さい。
(パスワードは、メニューで「ツール(T)→○○のプロパティ(E)」
 をクリックして表示されるダイアログの『保護』タブで設定と
 解除ができます: 一応、参考まで。)
「ACCESSのサブフォームコピーについて」の回答画像17
    • good
    • 0
この回答へのお礼

できました!!!
感動です(T▽T)
ありがとうございます!

エラーの原因は画像で頂いた、メインフォームのIDの名前が違いました。
変更した記憶もなく・・・。
数年前から積み重ねてきたファイルだったので、何かの時に編集したままになっていたのでしょう(汗

ともかく、思った通りの動作になりまして大変満足しております。
説明も分かりやすく、とても感謝してます。

ありがとうございました。

お礼日時:2010/05/19 20:33

No.14です。



> コピー後にメインフォームの一番左上に画面を移動したい
> のですが、可能でしょうか?

可能です。
・・・可能なんですが、その動作の検証のためにサンプルを
動かしてみたところ、動作に重大な欠陥が発生することが
わかりました(汗)

具体的には、2回目以降のコピーでエラーが発生し、画面上
はコピーされているように見えるのに、その状態でフォームを
閉じてから再度開くと、2回目のサブフォーム分のレコードが
なくなっている、という恐ろしいものです(汗)
大変申し訳ありません。

ただ、対処方法は既にわかっていて、またコードの改変幅は
小さいので、今回ご希望の動作と併せても、数行の改修で
済みますので、その点はご安心下さい(汗)

No.7のコードからの改修箇所と、改修後のコードは以下の
通りです(サブフォームのIDの書換部分):

【改修前】
   Me!サブテーブル.Form.Refresh
   '但し、前回回答により、以下に差し替え済みのはず
   'Me!(サブフォーム名).Form.Refresh

【改修後】
'※上記1行を削除し、以下のコードに差し替えます:
   Me!ID.SetFocus
   Me!(サブフォーム名).SourceObject = Me!(サブフォーム名).SourceObject
   Me.GotoPage 1, 0, 0


・・・以上です。
『改ページ』を入れていない限り、表示中のフォームの
領域が(何レコード目であるかには関係なく)1ページ目、
という数え方をされるので、「Me.GotoPage」の第1引数に
「1」を指定し、その左上隅の座標である「0, 0」を第2及び
第3引数に指定しています。
(『改ページ』は、フォームのデザインビューで、フォーム
 デザイン用のツールバーの中(『コマンドボタン』のボタン
 の隣)にあります:
 意図的に追加していない限り、気にしなくてOKです(汗))


なお、差し替え後の2行目のコードの右辺については、サブ
フォームの表示用フォーム(→今度はコントロールではなく、
「ソースオブジェクト」に指定しているフォームの名前の方)を
直接指定してもOKです:

【改修後・パターン2】
   Me!ID.SetFocus
   Me!(サブフォーム名).SourceObject = "SF_サブ"
   '右辺はダブルクォート(")で括る必要があります。
   Me.GotoPage 1, 0, 0


・・・以上です。
前回のコードで既に本番データの入力作業を実行されて
いないことを祈ります(汗)
重ねてお詫び致します。
(内容が内容だけに、本当にしゃれになりません・・・)

この回答への補足

回答ありがとうございます。

サブレコードが消える件は、幸いまだWebを見ていませんでした。
念のためテストデータで検証後に本データに反映させますので、数日のタイムラグはありますので大丈夫です(^^)

「438:オブジェクトは、このプロパティまたはメソッドをサポートしていません。」

というエラーメッセージが出ました。
フォーカスはサブフォームのレコードを貼り付けたところで止まっています。

Me!ID.SetFocus
Me!サブフォームの表示コントロール名.SourceObject = Me!サブフォームの表示コントロール名.SourceObject
Me.GotoPage 1, 0, 0

ということですよね?
念のため【改修後・パターン2】も試してみましたが、同じエラーが出てしまいました。
ダブルクォートの中はサブフォーム名にしましたが。(ソースオブジェクトの方)

補足日時:2010/05/18 21:25
    • good
    • 2

>最初のメッセージボックスで「キャンセル」


>を押してもコピーが実行されるようです。

忘れていました。訂正しました。それから
コピーの順序を変えました。コードが複雑に
なるのであっさりと。

>あ、あと今気付いたのですが、メインレコードの
>最後のレコードを削除してしまうと(IDに欠番が
>出たすぐ後)サブレコードがコピーされないようです。
>これは、メインレコードの最後のID+1(つまりメイン
>レコードのコピー後のID)の値をいつも代入する、
>のような感じですることは出来ますでしょうか。

これはメインテーブルのIDがオートナンバーだから
と思いますが。データの削除を伴う場合がるときは
一般的には主キーこの場合はIDですが、を連続番号
を発行するようにして対応します。
しかし、いずれにしてもメインレコードだけを
削除するのではなく、メインレコードに紐付け
られたサブフォームのレコードも同時に削除
しないと幽霊レコードがサブテーブルに残る
ことになります。

>「i」とはどういった意味なんでしょうか。

コードの最初に Dim i As Long と宣言して
いるように、数値型(長整数型)の変数でこれに
数値を代入していろいろします。



それでは以下、訂正したコードです。



Private Sub コピー開始()
Dim db As Database
Dim rsm As Recordset
Dim rs As Recordset
Dim rst As Recordset
Dim i As Long


On Error GoTo Er_ha

Set db = CurrentDb
Set rs = db.OpenRecordset("サブテーブル", dbOpenDynaset)
Set rsm = db.OpenRecordset("メインテーブル", dbOpenDynaset)
Set rst = Me!サブフォーム表示コントロール名.Form.RecordsetClone

If MsgBox("◆内容のコピーを作成しますか?◆", vbOKCancel) = vbCancel Then
GoTo Er_ha

Else
rsm.MoveLast
i = rsm!ID

'サブフォームのデータのコピー
If rst.RecordCount > 0 Then
With rst
rst.MoveFirst
Do Until .EOF
rs.AddNew
'IDは必要ないと思われるのでコメントアウトしておきます。
'必要なら先頭の'をはずしてください。
rs![ID] = i + 1
rs![ライセンス数] = rst![ライセンス数]
rs![開始日] = rst![開始日]

'以下、他に項目があるならその他の項目を置き換えてください。
'必要なときは先頭の'をはずしてください
'同様にして他の項目を追加してください。

'rs![その他の項目] = rst![その他の項目]
rs.Update
rst.MoveNext
Loop

End With
Else
End If

'メインフォームのコピー
DoCmd.DoMenuItem acFormBar, acEditMenu, 8, , acMenuVer70
DoCmd.DoMenuItem acFormBar, acEditMenu, 2, , acMenuVer70
DoCmd.DoMenuItem acFormBar, acEditMenu, 5, , acMenuVer70

MsgBox ("コピー終了しました")
DoCmd.RunCommand acCmdSaveRecord
End If
'エラー処理
Er_ha:
If Err.Number <> 0 Then
MsgBox (Err.Number & vbCrLf & Err.Description)
End If


rs.Close
Set rs = Nothing
rst.Close
Set rst = Nothing
rsm.Close
Set rsm = Nothing
db.Close
Set db = Nothing
End Sub



なお、レコードの削除と連続番号の発行方法については
必要なら提案します。その場合はテーブルのIDフィールドの
データ型の変更、コードの追加と変更が必要になります。
    • good
    • 0
この回答へのお礼

何回もとても親切に教えて頂いてありがとうございました。

結果、別の方法で解決しましたが、piroin654様には大変お世話になりました。

ありがとうございました。

お礼日時:2010/05/19 20:35

No.11です。



> どこかにサブフォームの表示コントロールに置き換える場所が
> ありましたらお教え下さい。

あ~・・・そういうことですか(汗)
「サブテーブル」という名前に引っ掛かりを感じてはいたんですが、
それはつまり、「サブフォームのレコードソースにしているテーブル」
ということだったんですね。

てっきり、サブフォームの表示コントロールの名前が「サブテーブル」
なのだと思っていました(汗)
すみませんが、No.7の回答で「サブテーブル」になっているところは
全て、サブフォームの表示コントロールの名前に置き換えてください。

【例】(コントロールの名前が「ライセンス情報」だった場合)
 <修正前>
 RecCnt = Me!サブテーブル.Form.RecordsetClone.RecordCount
 <修正後>
 RecCnt = Me!ライセンス情報.Form.RecordsetClone.RecordCount

いちいち更新するのは面倒だと思いますので、置き換えるコードの
どこか適当なところにカーソルを置いた状態でCtrl+Hキーを同時に
押して置換ダイアログを呼び出し、検索文字列と置換文字列を指定
の上、『対象』に「カレント プロシージャ(P)」を指定して、置換ボタン
をクリックして下さい。
(検索条件などを間違えた場合は、置換ダイアログを閉じた上で、
 Ctrl+Zキーの同時押しで元に戻せます)


・・・それと、No9の方への補足への横レスになりますが(汗)、
そこでサブフォーム側のIDが1だけ小さくなっているのは、メイン側
のレコードが、貼り付けただけで保存されていないのが原因です。

ですので、対処方法としては、単純に代入値を+1するのではなく、
メイン側の貼り付け後に「レコード保存」を追加するのが、根本的な
解決策となります。
(私がしたNo.7の回答で、メイン・サブそれぞれの複製のところで
 「RunCommand acCmdSaveRecord」を入れているのもそのため)
※DoMenuItemでの「レコードの保存」の引数がいくつになるかは、
  (RunCommandでやるのが正統ということもあり)調べていません。

そうしないと、もしもメイン側とサブ側のそれぞれのIDにリレーション
シップが組まれていて、参照整合性を設定していた場合(→今回の
事例は本来そうされているべき事案かと)、恐らくエラーが発生する
はずです。
(「テーブル'メイン'にリレーションシップが設定されたレコードが
 必要なので、レコードの追加や変更を行うことはできません」と
 いった感じで)


【参考まで】
リレーションシップ・参照整合性について:
http://www.relief.jp/itnote/archives/000497.php

リレーションシップの設定方法:
http://www.officepro.jp/access/relation/index3.h …

この回答への補足

回答ありがとうございます!

出来ました!!!!
すごくうれしいです!!ありがとうございます(T▽T)
この方法でしたら欠番も大丈夫ですね。

あとひとつだけ良いでしょうか。
コピー後にメインフォームの一番左上に画面を移動したいのですが、可能でしょうか?
メインフォームには縦横にスクロールバーが出ていて、微妙に1画面に収まりきりません。
コピー後にサブフォーム(メインフォームの右下にあります)にフォーカスがあるので、
画面が右下に寄っていて、その都度左上までマウスで移動してメインを入力する感じになります。

左上が本当はいいのですが、難しければフォーカスの移動でもいいです。
メインフォームの"ID"に移動など。

宜しくお願いいたします。

補足日時:2010/05/17 21:38
    • good
    • 0

サブフォームのデータコピーのところです。


うまくいきますように。

この回答への補足

度々すみません、最初のメッセージボックスで「キャンセル」を押してもコピーが実行されるようです。

補足日時:2010/05/17 01:11
    • good
    • 0

>メインフォームのコピー後のIDより1つだけ小さい


>IDでサブフォームがコピーされています。

プログラムの中ほどの

>rs![ID] = i



rs![ID] = i + 1

としてください。

この回答への補足

できました!ありがとうございます!

ちなみに
>rs![ID] = i

の「i」とはどういった意味なんでしょうか。今後の為に覚えておきたいです。

あと、コピー後の画面にて、サブフォームにはコピー前のIDのレコードが表示されてしまいます。
メインのレコードを移動して戻ってくるとちゃんとコピー後のIDのレコードが表示されます。
サブレコードの再読み込み?のようなことをすればコピー後にすぐ表示されるような気がするのですが、やりようはありますでしょうか。
このままだと、コピー後すぐにサブレコードを編集してしまうと前のIDのものを編集してしまい、間違いのもとになりそうです。

あ、あと今気付いたのですが、メインレコードの最後のレコードを削除してしまうと(IDに欠番が出たすぐ後)サブレコードがコピーされないようです。
これは、メインレコードの最後のID+1(つまりメインレコードのコピー後のID)の値をいつも代入する、のような感じですることは出来ますでしょうか。
それか他に解決方法がありますでしょうか。

何回も度々恐れ入りますが宜しくお願いいたします。

補足日時:2010/05/17 01:01
    • good
    • 0

No.7です。



> 「サブテーブル」の部分を本物のサブテーブルの名前にする
> だけだと思うのですが、それで合っていますでしょうか。

それで問題ないはずです。
(敢えて挙げるなら「ID」もですが、これは既にそちらと同名のはず)

こちらのサンプルで、一旦サブフォームの名前を変えて実行したところ、
同じ「Err.Number=2465」のエラーが発生しましたので、「サブテーブル」
という名前が、実際にフォームで使われているものと合っていない、
ということで間違いないものと思います。

なお、ここで使用する名前は、サブフォームのプロパティシートの
『その他』タブにある『名前』欄に表示されるものの方になります。
『データ』タブの『ソースオブジェクト』欄に表示される方ではない
ので、ご注意下さい。
(双方が同じ場合は、問題ありません)

また、具体的にどの行がエラーを起こしているのかを確認したい
場合は、前回提示したコードの先頭の「On Error~」の頭に「'」を
追加して独自のエラー処理を無効にして、再度処理を実行して
みてください。
(エラーメッセージ内に表示される、『デバッグ』ボタンをクリックする
 ことで、該当行を黄色表示させることができます:
 VBAに表示用のパスワードが掛かっている場合は、先に認証を
 通しておかないと、同ボタンは使用できないのでご注意下さい)
※今回はメッセージ内で「サブテーブル」という名前が表示されている
 ので、そこまでする必要はないかと思いますが、今後の参考まで。


> 旧バージョンとはACCESSのことでしょうか。。

はい、Accessのことです。
Access2003のDoMenuItemのヘルプには、以下の説明があります:

> メモ Access 97 で、DoMenuItem メソッドは RunCommand メソッド
> に置き換えられました。DoMenuItem メソッドは、以前のバージョンの
> Access との互換性を保つためにのみ、このバージョンに含まれています。

Access97はAccess2000の前ですから、Access2000でも推奨されるのは
RunCommandメソッドになりますので、置き換えました。

組み込み定数については、以下のようなサイトもありますので参考まで:
http://www.accessclub.jp/runcommand/


> サブフォームはデータシートでなければだめでしょうか。。

失礼、言葉が足りていませんでした(汗)
「もしテーブルを直接使用していたなら、フォームで同様の見た目をした
ものもあります(=データシート型)」という意味です。
元からフォームを使用されているのでしたら、それで問題ありません。


・・・長くなりましたが(汗)、以上です。

この回答への補足

回答ありがとうございます。

>なお、ここで使用する名前は、サブフォームのプロパティシートの
>『その他』タブにある『名前』欄に表示されるものの方になります。
>『データ』タブの『ソースオブジェクト』欄に表示される方ではない
>ので、ご注意下さい。

こちらですが、サブフォームの表示コントロールのことでしょか?
教えて頂いた式の中にサブフォームの表示コントロールを記載するところがありましたでしょうか?
どこかにサブフォームの表示コントロールに置き換える場所がありましたらお教え下さい。

宜しくお願いいたします。

補足日時:2010/05/16 18:47
    • good
    • 0

たぶん、データはコピーと表示ができると思いますが、


フィールドが100あると聞いてあわててしまい
ました。必要なものも抜かしていたかもしれ
ません。長々とした回答で申し訳ないです。
まだ、油断はできないのですが、何かあれば
メッセージを送ってください。
    • good
    • 0

訂正しました。

どうですか。


Private Sub mcdコピー開始_Click()
Dim db As Database
Dim rsm As Recordset
Dim rs As Recordset
Dim rst As Recordset
Dim i As Long


On Error GoTo Er_ha
Set db = CurrentDb
Set rs = db.OpenRecordset("サブテーブル", dbOpenDynaset)
Set rsm = db.OpenRecordset("メインテーブル", dbOpenDynaset)
Set rst = Me!サブフォーム表示コントロール名.Form.RecordsetClone

'MsgBoxで引数たとえばvbOKCancelなどを設定するときは()でかこいません
MsgBox "◆内容のコピーを作成しますか?◆", vbOKCancel
If vbOK Then
'メインフォームのデータのコピー

DoCmd.DoMenuItem acFormBar, acEditMenu, 8, , acMenuVer70
DoCmd.DoMenuItem acFormBar, acEditMenu, 2, , acMenuVer70
DoCmd.DoMenuItem acFormBar, acEditMenu, 5, , acMenuVer70

rsm.MoveLast
i = rsm!ID


'サブフォームのデータのコピー
If rst.RecordCount > 0 Then
With rst
rst.MoveFirst
Do Until .EOF
rs.AddNew
'IDは必要ないと思われるのでコメントアウトしておきます。
'必要なら先頭の'をはずしてください。
rs![ID] = i
rs![ライセンス数] = rst![ライセンス数]
rs![開始日] = rst![開始日]

'以下、他に項目があるならその他の項目を置き換えてくださ

い。
'必要なときは先頭の'をはずしてください
'同様にして他の項目を追加してください。

'rs![その他の項目] = rst![その他の項目]
rs.Update
rst.MoveNext
Loop

'MsgBox ("サブフォームのコピー終了")
End With
Else
' MsgBox ("サブフォームにレコードがありません。")
End If
MsgBox ("コピー終了しました")
End If
'エラー処理
Er_ha:
If Err.Number <> 0 Then
MsgBox (Err.Number & vbCrLf & Err.Description)
End If


rs.Close
Set rs = Nothing
rst.Close
Set rst = Nothing
rsm.Close
Set rsm = Nothing
db.Close
Set db = Nothing
End Sub

この回答への補足

回答ありがとうございます。

非常におしいです!
メインフォームのコピー後のIDより1つだけ小さいIDでサブフォームがコピーされています。

コピー前メインID=サブID=12659
コピー後メインID=16989、サブID=16988

おしいです!
これの解決方法ありますでしょうか。

補足日時:2010/05/16 18:53
    • good
    • 0

最初の回答の"この回答への補足"で、


[サブフォームの表示コントロール]の名前を
サブフォームと同じにした、ということですが
このようにすると何かと混乱のもとになるので
例えば、サブフォームの名前が
サブフォーム1ならば、コントロールの
名前は違う名前、たとえばサブフォーム1sub
あるいはobjサブフォーム1のように変えてください。
ときにはコードが動きません。サブフォームの
データが取れないのもそのあたりにあります。

提示したコードでは

Set rst = Me!サブフォーム表示コントロール名.Form.RecordsetClone

の部分も変更します。

それから、

>メインテーブルのフィールドが100を超える為、
>教えて頂いたように行数を足していくのは
>現実的ではありません。

このようなことは最初に情報をくださいませ。

では、du-samaさんが最初に提示したコードを
そのまま利用して、以下のようにします。



Private Sub mcdコピー開始_Click()
Dim db As Database
Dim rsm As Recordset
Dim rs As Recordset
Dim rst As Recordset
Dim i As Integer


On Error GoTo Er_ha
Set db = CurrentDb
Set rs = db.OpenRecordset("サブテーブル", dbOpenDynaset)
'サブフォーム表示コントロール名は変更してください。
Set rst = Me!サブフォーム表示コントロール名.Form.RecordsetClone

'MsgBoxで引数たとえばvbOKCancelなどを設定するときは()でかこいません
MsgBox "◆内容のコピーを作成しますか?◆", vbOKCancel
If vbOK Then
'メインフォームのデータのコピー

DoCmd.DoMenuItem acFormBar, acEditMenu, 8, , acMenuVer70
DoCmd.DoMenuItem acFormBar, acEditMenu, 2, , acMenuVer70
DoCmd.DoMenuItem acFormBar, acEditMenu, 5, , acMenuVer70

'サブフォームのデータのコピー
If rst.RecordCount > 0 Then
With rst
rst.MoveFirst
Do Until .EOF
rs.AddNew
'IDは必要ないと思われるのでコメントアウトしておきます。
'必要なら先頭の'をはずしてください。
'rs![ID] = rst![ID]
rs![ライセンス数] = rst![ライセンス数]
rs![開始日] = rst![開始日]

'以下、他に項目があるならその他の項目を置き換えてください。
'必要なときは先頭の'をはずしてください
'同様にして他の項目を追加してください。

'rs![その他の項目] = rst![その他の項目]
rs.Update
rst.MoveNext
Loop
End With
Else
End If
MsgBox ("コピー終了しました")
End If
'エラー処理
Er_ha:
If Err.Number <> 0 Then
MsgBox (Err.Number & vbCrLf & Err.Description)
End If


rs.Close
Set rs = Nothing
rst.Close
Set rst = Nothing
db.Close
Set db = Nothing
End Sub

この回答への補足

メインフォームとサブフォームがコピーされましたが、'サブフォームのデータのコピー
のところでIDをコピーしないようにすると、サブレコード自体はコピーされているようですが、IDが空白の為、コピー後のメインフォームに埋め込まれたサブフォームに表示されません。
IDをコピーするように’を外したところ、やはりコピー前のIDと同じになってしまいました。

メインコピー後のIDを代入する必要がありそうですが・・・。頂いた式で普通は出来るんですよね。。困りました。
今更ですが、ACCESS2000です。何か関係あるでしょうか。。

補足日時:2010/05/15 23:53
    • good
    • 0

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QAccess:サブフォームのレコードのコピー(複数)

Accessにて販売管理システムを構築しています。
以下の構成にてテーブルがあります。
------------------------------
T_見積伝票(メイン)
 ・見積ID(主キー)
 ・顧客名
 ・見積日
------------------------------
T_見積明細(サブ)
 ・明細ID(主キー)
 ・見積ID
 ・商品名
 ・数量
 ・単価
------------------------------
T_受注伝票(メイン)
 ・受注ID(主キー)
 ・顧客名
 ・受注日
------------------------------
T_受注明細(サブ)
 ・明細ID(主キー)
 ・受注ID
 ・商品名
 ・数量
 ・単価
------------------------------
*主キーはすべてオートナンバーにて採番されるようにしています。
T_見積伝票とT_見積明細がリレーション
T_受注伝票とT_受注明細がリレーション

実現したいことは、T_見積伝票&T_見積明細に入力された内容が
実際に受注となった場合、「受注に転記」のようなボタンを設置し
クリックすることで、T_受注伝票&T_受注明細に複製できればと思っています。
T_見積伝票とT_受注伝票にはいくつか異なるフィールドがあるので、(見積日と受注日)
対応するフィールドの内容のみコピーしたいです。
逆にT_見積明細とT_受注明細は主キーとなってるIDのみ違うだけで
それ以外は全て同じフィールドにて構成されていますので
全部コピーしたいです。

色々と調べた結果、追加クエリを使うといいみたいですが
追加クエリ自体がよく分からず質問させて頂きました。
宜しくお願い致します。

Accessにて販売管理システムを構築しています。
以下の構成にてテーブルがあります。
------------------------------
T_見積伝票(メイン)
 ・見積ID(主キー)
 ・顧客名
 ・見積日
------------------------------
T_見積明細(サブ)
 ・明細ID(主キー)
 ・見積ID
 ・商品名
 ・数量
 ・単価
------------------------------
T_受注伝票(メイン)
 ・受注ID(主キー)
 ・顧客名
 ・受注日
------------------------------
T_受注明細(サブ)
 ・明細ID(主キー)
 ...続きを読む

Aベストアンサー

>この記述で複数の明細をコピーできるのでしょうか?
出来ますよ。条件を満たすレコードを自動的に全て追加できます。

例えば、見積伝票(見積ID=1)に複数の明細がある場合、

SELECT * FROM T_見積明細 WHERE T_見積明細.見積ID = 1;

上記の【選択】クエリで、複数のレコードが【選択】できますよね。これと同様に【追加】クエリなら、複数のレコードが【追加】されます。SQL(クエリ)の便利なところです。こういう言語を非手続き型言語と言います。

今回のプログラムでは、受注IDの問題があったので、前半はDAOのRecordsetを使って、手続き型の処理をしています。後半はSQLを使って非手続き型の処理をしています。

QAccessでレコードの複製

Accessで、ボタンをクリックすると
表示させているレコードをコピーして複製したいです。
以下のようにコードを書いてみたのですが、
「コマンドまたはアクション”追加貼り付け”は無効です」
となってしまいます。

DoCmd.RunCommand acCmdSelectRecord 'レコードの選択
DoCmd.RunCommand acCmdCopy 'コピー
DoCmd.RunCommand acCmdRecordsGoToNew '新規レコードへ
DoCmd.RunCommand acCmdSelectRecord
DoCmd.RunCommand acCmdPasteAppend '追加貼り付けを実行

ちなみに
DoCmd.RunCommand acCmdPasteAppend

DoCmd.RunCommand acCmdPaste
に修正しても
「コマンドまたはアクション”貼り付け”は無効です」
となって、エラーになってしまいます。

そこで、以下のようにコードを省略して
DoCmd.RunCommand acCmdSelectRecord 'レコードの選択
DoCmd.RunCommand acCmdCopy 'コピー
DoCmd.RunCommand acCmdRecordsGoToNew '新規レコードへ
DoCmd.RunCommand acCmdSelectRecord
ここで、手動で、ctrl+Vをすると、レコードのコピーができます。

コードの書き方が間違っているのでしょうか?
ご教授よろしくお願いいたします!

Accessで、ボタンをクリックすると
表示させているレコードをコピーして複製したいです。
以下のようにコードを書いてみたのですが、
「コマンドまたはアクション”追加貼り付け”は無効です」
となってしまいます。

DoCmd.RunCommand acCmdSelectRecord 'レコードの選択
DoCmd.RunCommand acCmdCopy 'コピー
DoCmd.RunCommand acCmdRecordsGoToNew '新規レコードへ
DoCmd.RunCommand acCmdSelectRecord
DoCmd.RunCommand acCmdPasteAppend '追加貼り付けを実行

ちなみに
DoCmd.RunCommand acCmdPasteAppend

Do...続きを読む

Aベストアンサー

#4です

> いただいたページを見てみると、
> サブフォームのコピーでエラーになるとのこと。
> 私の場合はその前の段階の、メインフォームのレコードのコピーでつまづいております・・・。

参照先の処理(AccessClub の方)は
・メインをコピーした後で
・サブフォームの元テーブルに対して該当レコードをコピー
という流れになっています。

メインをコピーする

> メインフォームのレコードを新規レコードにコピーする
> DoCmd.RunCommand acCmdSelectRecord 'カレントレコードの選択
> DoCmd.RunCommand acCmdCopy '選択レコードのコピー
> DoCmd.GoToRecord , , acNewRec '新規レコードに移動
> ' DoEvents ' (必要に応じて)
> DoCmd.RunCommand acCmdPasteAppend 'コピーレコードの追加貼り付け
>
> DoCmd.RunCommand acCmdSaveRecord '保存

部分について、みてもらいたかったのですが・・・
で、上記の DoEvnts 部分を有効にしてみてどうなりますか?

(あれを確認していた際、2007 で、その時の最新状態になっていたと思います)

#4です

> いただいたページを見てみると、
> サブフォームのコピーでエラーになるとのこと。
> 私の場合はその前の段階の、メインフォームのレコードのコピーでつまづいております・・・。

参照先の処理(AccessClub の方)は
・メインをコピーした後で
・サブフォームの元テーブルに対して該当レコードをコピー
という流れになっています。

メインをコピーする

> メインフォームのレコードを新規レコードにコピーする
> DoCmd.RunCommand acCmdSelectRecord 'カレントレコードの選択
> DoCmd.RunCommand ac...続きを読む

QAccessでレコードの複製

Access2010を使用して入力フォームを作成しています。

メインフォームとサブフォームにそれぞれ顧客情報を表示させていて、
「複製」ボタンを押すと、
メインフォーム、サブフォームのレコードがコピーされるようにしています。

メインフォームの元テーブルはJIK
サブフォームの元テーブルはREN
です。

JIKおよびRENテーブルはほかからリンクさせているのですが、
これで「複製」ボタンを押すと、
"実行時エラー '3022': インデックス、主キー、またはリレーションシップで重複する値が生成されるためテーブルに要求した変更でした成功しました。フィールドまたは重複データが含まれている、インデックスを削除するフィールド内のデータを変更または重複するエントリを許可して、やり直してのインデックスを再定義します。このエラーは、レポートやレポートの生成に変更を保存するときに発生します。
が出てしまいます。

テーブルをインポートすると正常に動作します。

テーブルをリンクさせる場合、レコードの複製は不可能なのでしょうか?

VBAは以下のように記述してみました。

Private Sub コマンド10_Click()
On Error GoTo Err_コマンド10_Click

Dim Result As Integer

Result = MsgBox("このデータを複製しますか?", vbYesNo + vbDefaultButton2 + vbQuestion, "データの複製確認")
If Result = vbYes Then

Me!txtCopy事件ID = Me!事件ID

Dim stDocName As String

DoCmd.RunCommand acCmdSelectRecord 'カレントレコードの選択
DoCmd.RunCommand acCmdCopy '選択レコードのコピー
DoCmd.GoToRecord , , acNewRec '新規レコードに移動
DoEvents ' (必要に応じて)
DoCmd.RunCommand acCmdPasteAppend 'コピーレコードの追加貼り付け

DoCmd.SetWarnings False ' システムメッセージ非表示
stDocName = "追加クエリ"
DoCmd.OpenQuery stDocName, acNormal, acEdit
DoCmd.SetWarnings True ' システムメッセージ表示

' サブフォーム再クエリ
Me!SREN.Requery

' 追加したレコードに移動
DoCmd.GoToRecord , , acLast
Me.リスト31.Value = Me.リスト31.ItemData(0)

MsgBox ("データを複製しました")

Exit_コマンド10_Click:
Exit Sub

Err_コマンド10_Click:
MsgBox Err.Description
Resume Exit_コマンド10_Click

Else

MsgBox "データの複製をキャンセルしました"

End If

End Sub

追加クエリは以下のように作成してみました。

【追加クエリ】
INSERT INTO REN ( 事件ID, 氏名, フリガナ, ・・・ )
SELECT [Forms]![MAIN]![事件ID] AS 式1, REN.氏名, REN.[フリガナ], REN.報告書, ・・・
FROM REN
WHERE (((REN.事件ID)=[Forms]![MAIN]![txtCopy事件ID]));

Access2010を使用して入力フォームを作成しています。

メインフォームとサブフォームにそれぞれ顧客情報を表示させていて、
「複製」ボタンを押すと、
メインフォーム、サブフォームのレコードがコピーされるようにしています。

メインフォームの元テーブルはJIK
サブフォームの元テーブルはREN
です。

JIKおよびRENテーブルはほかからリンクさせているのですが、
これで「複製」ボタンを押すと、
"実行時エラー '3022': インデックス、主キー、またはリレーションシップで重複する値が生成されるためテーブル...続きを読む

Aベストアンサー

【つづき】

Me.Dirty 部分は、編集中なら保存してみて、まだ編集中なら何かあったんでしょう。
処理せずに抜けます。
オートナンバの「事件ID」が Null なら新規レコードなんでしょう。
コピーするものはないので抜けます。

フォームの表示を抑止してから
現在の「事件ID」を覚えておいてコピー処理に突入

  With Me.Recordset
    ・・・・・
  End With

部分がメインフォームに表示しているレコードのコピー処理になります。
Me.RecordsetClone を、現在表示しているレコードに同調させます。

    For i = 0 To .Fields.Count - 1
      Select Case .Fields(i).Name
        Case "事件ID"
        Case Else
          .Fields(i) = rs(i)
      End Select
    Next

部分で各フィールドの値を設定(コピー)していきますが、
「事件ID」はオートナンバなので値を設定しない様にします。
Me.Recordset に追加したので、メインフォームでは追加したものがカレントになってます。
ということは、オートナンバ「事件ID」は新しく採番された値となります。

  Set rs = CurrentDb.OpenRecordset("SELECT * FROM REN WHERE 事件ID=" & iSave)
  ・・・・・
  Set rs = Nothing

部分がサブフォームの元になっているテーブル「REN」への追加になります。
テーブル「REN」の「事件ID」が、元の「事件ID」と一致するものを抽出します。
一致するものがなければ何もしません。
何かしらあったら、レコードセットの複製( Clone )を作ります。
これにより、フィールドの順が同じものが作られることになります。
フィールド順が同じという事は、フィールド何番目を何番目に代入・・・・
この、何番目が一緒になることを意味します。
抽出条件に一致するものがあったら、何件かわかりませんが複製元を最後に移動します。
前に向かって、抽出されたレコード数分フィールドの値を同じに(代入)していきます。

      For i = 0 To rs.Fields.Count - 1
        Select Case rs(i).Name
          Case "連絡先ID"
          Case "事件ID"
            rsC(i) = Me.事件ID
          Case Else
            rsC(i) = rs(i)
        End Select
      Next

ここでもメインと同様に、オートナンバ「連絡先ID」なら値を設定しない様に。
また、「事件ID」は新しく採番された「Me.事件ID」を設定する様に・・・・
(「Me.事件ID」は前述したように追加した後のものになっているので・・・)
で、サブフォーム元のテーブルに追加した後、リンク親/子フィールドが設定されていたとすると、
  Me.Recalc
で、フォーム内(メイン/サブとも)の表示が変わったと思います。変わらなければ
> ' サブフォーム再クエリ
> Me!SREN.Requery
でも・・・
最後に、フォームの表示抑止を解除します。

専用の記述にすると、上記の様になるかと思います。
その処理専用のクエリを作成して・・・・でも良いと思いますが、
最低限のフィールド名(除外するもの/値を更新するもの)がわかっていれば、
少ない記述でできるものと思います。

ただ、注意する事があって、
Clone したものに追加すると、Clone 元の最後に追加された事になるので、
Clone 元での rs.EOF 判別は、出現しない事になります。
(単に MoveNext していたのでは ・・・ ということは、無限ループに陥ることに)
何レコードを複写(コピー)するとした場合、初期レコード数分 For で MoveNext するか、
最後にいってから、前に( MovePrevious )前にで先頭を越すか( While (Not rs.BOF) )
のどちらかになると思います。

今回は、前に前に・・・の方法を提示してみました。
(抽出されるのは1件だけ・・・・であれば、MoveLast / MovePrevious 等は不要ですけど)

※ この方法での利点を挙げるとすれば、
 仕様変更等により、各テーブルのフィールド数に増減があったとしても修正しなくても良い
 (除外・更新する部分に変更あれば、修正は必要ですが・・・)


参考にする/しない等々含め、自己責任でお願いします。


蛇足1)

> DoEvents ' (必要に応じて)

このようなコメントは不要と思います。
読んでわかるレベルのものならば、コメントはない方が良いかも
コメントは、読んでもわからない理由を記述しておくものと思います。
例えば、

DoEvents ' そのまま実行すると次行で 2046 エラーになるため、一息入れる

とか?


蛇足2)

No77233.サブフォームのレコードのコピーができない
http://www.accessclub.jp/bbs/0240/beginers77233.html

にある CopyRec は、
オートナンバはない & 抽出は1件を条件に、使い回しできるように・・・でした

【つづき】

Me.Dirty 部分は、編集中なら保存してみて、まだ編集中なら何かあったんでしょう。
処理せずに抜けます。
オートナンバの「事件ID」が Null なら新規レコードなんでしょう。
コピーするものはないので抜けます。

フォームの表示を抑止してから
現在の「事件ID」を覚えておいてコピー処理に突入

  With Me.Recordset
    ・・・・・
  End With

部分がメインフォームに表示しているレコードのコピー処理になります。
Me.RecordsetClone を、現在表示しているレコードに同調させます。

 ...続きを読む

QAccess サブフォームでの選択行の取得

こんにちは。

Access初心者です。

サブフォームでテーブルの項目を表示させていますが、
選択された行を取得する方法はありますか?
サボフォームの下の方に現在選択されているレコード数が表示されてますが、その値でかまいません。

調べているのですが、なかなか検討がつきません。
宜しくお願い致します。

Aベストアンサー

フォーム名がフォーム1、サブフォームコントロールの名前がサブフォーム1だとすると、

Forms!フォーム1!サブフォーム1.Form.CurrentRecord

で取得できます。
(「Forms」と「Form」がありますのでご注意下さい)


また、フォーム1にコードを記述する場合であれば

Me!サブフォーム1.Form.CurrentRecord

サブフォーム1へのコード記述であれば

Me.CurrentRecord

という構文によっても、それぞれ取得が可能です。

QAccessのRefresh・Requery・Repaintの違い

Requeryはもう一度ソースレコード(テーブル)を読み込むようです。このとき、テーブルの先頭レコードに移動してしまいます。
Refreshは最新のレコード(テーブル)を再表示するような気がします。レコードの移動は起こらない気がします。
Repaintは、VBAでキャプションなどを変更したとき使っています。
でも、よくわかっていません。
どんなときにどんなメソッドを使えばいいのでしょうか?
詳しい方、よろしくお願いいたします。

Aベストアンサー

たびたびすみません。
調べてたらこんなのがでてきました。
http://www.nurs.or.jp/~ppoy/access/access/acF007.html

参考URL:http://www.nurs.or.jp/~ppoy/access/access/acF007.html

Qaccess2000:フォームで入力した内容を新規レコードにコピー

初歩的な質問ですが困っています。表記の通りにAというテーブルへ入力フォームを使いデータ入力しています。そこでほぼ同じ内容の入力項目が数十件発生する時があります。そのために入力フォームで作成したデータをそのまま新規レコードへコピーしコピー後に手直ししようと考えています。がどうすればよいのか妙案がうかびません。ヒントでもいいので教えてください。

Aベストアンサー

Ctrl+7 ではダメですよね?


コマンドボタンのクリック時イベントで以下のコードを記述すれば、
選択していたレコードを、新規レコードにコピーできると思います。

DoCmd.RunCommand acCmdSelectRecord
DoCmd.RunCommand acCmdCopy
DoCmd.RunCommand acCmdRecordsGoToNew
DoCmd.RunCommand acCmdSelectRecord
DoCmd.RunCommand acCmdPaste

QACCESS フォームからサブフォームのデータを更新・入力したい

ACCESS フォームからサブフォームのデータを更新・入力したい

tbl_プロジェクトというテーブルにIDとプロジェクトコード、プロジェクトの基本情報を持たせ、f_プロジェクトフォームからプロジェクトコード、件名、契約日等のデータ及び、f_テーマサブフォームにテーマを入力できるようなフォームを作成しています。フォームで入力したものをそれぞれのテーブルに保存したいのですがうまくいかない部分があります。

フォームから入力すると、tbl_プロジェクトに所属する情報は更新されます。そのtbl_プロジェクトに所属するプロジェクトコードをサブフォームのtbl_テーマのプロジェクトコードにも反映したいのですがどのようにしたらよいでしょうか?
そういったことは可能でしょうか?分かりにくい説明で申し訳ないですが教えていただけると助かります。よろしくお願いします!



DBの構成
【テーブル】
tbl_プロジェクト (1件1件のIDとプロジェクトコードを持つ)
(フィールド:P_ID、プロジェクトコード、件名、契約日など)
tbl_テーマ(プロジェクト毎に関連のあるキーワードを持つ)
(フィールド:P_ID、プロジェクトコード、テーマ)←これのプロジェクトコードにtbl_プロジェクトのデータが入るようにしたい。
tbl_顧客(プロジェクトを依頼した顧客情報を持つ)
【クエリ】
q_テーマ(プロジェクト、テーマ、顧客を抽出するクエリ)
【フォーム】
f_プロジェクト (プロジェクトを1件ずつ表示・参照・新規作成するフォーム)
f_テーマサブフォーム (f_プロジェクトフォームのプロジェクトコードにづきテーマを
        表示・入力するサブフォーム)

リレーションはP_IDをキーに一対多で作成しています。

ACCESS フォームからサブフォームのデータを更新・入力したい

tbl_プロジェクトというテーブルにIDとプロジェクトコード、プロジェクトの基本情報を持たせ、f_プロジェクトフォームからプロジェクトコード、件名、契約日等のデータ及び、f_テーマサブフォームにテーマを入力できるようなフォームを作成しています。フォームで入力したものをそれぞれのテーブルに保存したいのですがうまくいかない部分があります。

フォームから入力すると、tbl_プロジェクトに所属する情報は更新されます。そのtbl_プロジェク...続きを読む

Aベストアンサー

No.4です。

前回の回答は、「レコードの新規登録」のみを想定していました(汗)
大変失礼致しました。


【「メインフォーム」-「サブフォームの新規レコード」間の不一致について】
(=No.4の補足での、2個目の「◆」の件)

メインフォーム側の「レコード移動時」イベントで、『プロジェクトコード』の
更新後イベントと同様の処理を行えば、解消すると思います。
(先頭1行が「Private Sub Form_Current()」となる他は、前回のVBAと全く
 同じなので、今回は省略します)


【既存レコードでの『プロジェクトコード』の空白について】
(=No.4の補足での、1個目の「◆」の件)

対処法としては、
 a)更新クエリを使用して、tbl_テーマの『プロジェクトコード』を一括更新
  (→tbl_テーマに入力済みの『P_ID』の再確認が不要な場合)
 b)「メインフォーム上のプロジェクトコードを、サブフォームの全レコードに
  一括代入」するためのコマンドボタンを、メインフォームに追加
  (→tbl_テーマの『P_ID』が正しいかを目視確認してから代入する場合)
の、2つの考え方があります。

「a」については添付画像をご覧いただくとして、ここでは「b」について説明
します。

メインフォームに『コード転記』コマンドボタンを作成したら、そのクリック時
イベントに以下のコードを記載して下さい:

Private Sub コード転記_Click()

  If MsgBox("サブフォームにプロジェクトコードを追記します", vbOKCancel, "確認") = vbCancel Then Exit Sub

  'サブフォームの全レコードを上書き更新
  With Me![サブフォームのコントロール名].Form.RecordsetClone
    Do Until .EOF
      .Edit
      !プロジェクトコード = Me!プロジェクトコード
      .Update
    Loop
  End With

  '更新を反映
  Me![サブフォームのコントロール名].Form.Refresh

  MsgBox "追記しました", , "確認"

End Sub


なお、「a/b」のどちらを採った場合でも、サブフォームの『P_ID』の上書き
編集に合わせて『プロジェクトコード』も連動して更新させるには、別途、
以下のような『P_ID』の更新後イベントでの対応が必要です:

Private Sub P_ID_AfterUpdate()
'メインではなくサブフォームの『P_ID』テキストボックスの更新後イベント

  If IsNull(Me!P_ID) Then
    Me!プロジェクトコード = Null
  Else
    Me!プロジェクトコード = DLookup("[プロジェクトコード]", "tbl_プロジェクト", "[P_ID]=" & Me!P_ID)
    '『P_ID』がテキスト型の場合は上記ではなく以下のコード
    'Me!プロジェクトコード = DLookup("[プロジェクトコード]", "tbl_プロジェクト", "[P_ID]='" & Me!P_ID & "'")
  End If

End Sub

また、この対応を組み込んで戴けば、

> テーマを修正するとフォーム上では10001が入力される。
> tbl_テーマには反映されない。

の件も解消すると思います。
(但し、別のレコードに移動したり、メニューから「レコード(R)→レコードの
 保存(O)」を選択する等して、レコードが保存してからでないと、テーブル
 には反映されないので、確認の際はご注意下さい)


・・・以上です。

No.4です。

前回の回答は、「レコードの新規登録」のみを想定していました(汗)
大変失礼致しました。


【「メインフォーム」-「サブフォームの新規レコード」間の不一致について】
(=No.4の補足での、2個目の「◆」の件)

メインフォーム側の「レコード移動時」イベントで、『プロジェクトコード』の
更新後イベントと同様の処理を行えば、解消すると思います。
(先頭1行が「Private Sub Form_Current()」となる他は、前回のVBAと全く
 同じなので、今回は省略します)


【既存レコードでの『プロジェクトコー...続きを読む

Qサブフォームに対してGoToRecordするには?

フォームに対してRequeryすると先頭のレコードへ移動してしまうので
Requeryする前のレコードの番号を取得して
Requery後にそのレコード番号へ移動したいのですが

Sub test()
i = Forms("Form").Controls("SubForm").Form.CurrentRecord
Forms("Form").Controls("SubForm").Requery
DoCmd.GoToRecord acActiveDataObject, Forms("Form").Controls("SubForm"), acGoTo, i
End Sub

これをすると、実行時エラー2498
指定した式は、いずれかの引数とデータ型が対応していません。
になりますが、
どこがおかしいのでしょうか?

Aベストアンサー

【要旨】
サブフォームのレコード移動では、対象サブフォームは引数で指定するのではなく、
SetFocusメソッドで移動後、引数を省略したGotoRecordを使用します:
  Forms("Form").Controls("SubForm").SetFocus
  DoCmd.GotoRecord , , acGoto, i

但し、「Requery前後でのレコード移動の回避」が目的の場合は、Requeryの
対象を「親フォームまたはサブフォームのFormオブジェクト」ではなく「サブフォーム
コントロール」とすればOkです。
 <現状・例1>
  Forms("Form").SetFocus
  DoCmd.Requery
 <現状・例2>
  Forms("Form").Requery
 <現状・例3>
  Forms("Form").Controls("SubForm").Form.Requery
 <代替策>
  Forms("Form").Controls("SubForm").Requery
  ※「現状・例3」との違い(→途中の「.Form」の有無)に注意。


【詳細】
> 実行時エラー2498

このエラーの直接の原因は、GotoRecordメソッドの第2引数に指定している
「Forms("Form").Controls("Subform")」の部分です。

ここに指定するのはオブジェクト名になりますが、そのデータ型は文字列型です。
一方、「~.Controls(~)」の形で指定した場合、取得できるのは
 a)オブジェクトそのもの
 b)そのオブジェクトのデフォルトプロパティ
のどちらかです(→状況によって変化します)。
(例えばテキストボックスなら、TextBoxオブジェクトまたはValueプロパティの値)

サブフォームのデフォルトプロパティは調べていませんが(汗)、少なくとも文字列
型のプロパティではないため、「型が一致しない」とのエラーとなります。
サブフォームのコントロール名を取得する場合は、
  Forms("Form").Controls("SubForm").Name
というように、Nameプロパティを明示的に指定する必要があります。

ただ、「サブフォームのレコード移動」の場合、明示的に「Name」プロパティを
指定しても解決には至りません(汗)
これは、GotoRecordメソッドの第2引数には、直接開いているオブジェクトの
名前のみが有効なためで、サブフォームを直接的に指定することはできない、
ということです。
(注:Microsoftの資料を探したわけではなく、経験則から記述していますので、
 私の勘違いでしたらご容赦願います(汗))

サブフォームのレコード移動には、冒頭に記述したとおり、「フォーカスの移動」と
「一部の引数を省略したGotoRecord」を使用します:
  Forms("Form").Controls("SubForm").SetFocus
  DoCmd.GotoRecord , , acGoto, i

なお、これも冒頭に書きましたが、サブフォームのRequeryの仕方には幾つか
方法がありますが、Requeryの対象を「コントロールとしてのサブフォーム」にすれば、
レコード移動が発生しませんので、GotoRecord自体が不要になります。
http://www.f3.dion.ne.jp/~element/msaccess/AcTipsFrmHowToRequeryAndReturn.html

【要旨】
サブフォームのレコード移動では、対象サブフォームは引数で指定するのではなく、
SetFocusメソッドで移動後、引数を省略したGotoRecordを使用します:
  Forms("Form").Controls("SubForm").SetFocus
  DoCmd.GotoRecord , , acGoto, i

但し、「Requery前後でのレコード移動の回避」が目的の場合は、Requeryの
対象を「親フォームまたはサブフォームのFormオブジェクト」ではなく「サブフォーム
コントロール」とすればOkです。
 <現状・例1>
  Forms("Form").SetFocus
  DoCmd.Requery
 <現...続きを読む

Qメインフォームとサブフォームのレコードを複製

(昨日同じ質問をあげましたがカテゴリが間違っていたのでこちらにあげなおしました)

メインフォーム「MAIN」にサブフォーム「REN」を埋め込んでいます。

【メインフォームMAIN】
テーブル名:JIK
ID:事件ID

【サブフォームREN】
テーブル名:REN
ID:連絡先ID(・事件ID)

ボタンをクリックすると、メインフォームで表示させているレコードを複製させたいです。

以下を参考に、そのとおり(のつもり)に作ってみたのですが
(メインフォーム「MAIN」に「txtCopy事件ID」という名前のテキストボックスも作成しました)
「コマンドまたはアクション”追加貼り付け”は無効です。」
とエラーメッセージが出てしまいます。
どのように修正すればよいでしょうか?
http://www.accessclub.jp/bbs3/0103/superbeg36719 …

ちなみに追加クエリだけを実行すると
表示させているメインフォーム「MAIN」のレコードに、
サブフォーム「REN」のレコードが追加され、
サブフォーム「REN」のレコードが2倍になりました。

以下追加クエリとコードです。

【追加クエリ】
INSERT INTO REN ( 事件ID, 氏名, フリガナ, ・・・ )
SELECT [Forms]![MAIN]![事件ID] AS 式1, REN.氏名, REN.[フリガナ], REN.報告書, ・・・
FROM REN
WHERE (((REN.事件ID)=[Forms]![MAIN]![txtCopy事件ID]));

【VBA】
Private Sub 明細コピー_Click()
On Error GoTo Err_明細コピー_Click

Me!txtCopy事件ID = Me!事件ID

DoCmd.DoMenuItem acFormBar, acEditMenu, 8, , acMenuVer70
DoCmd.DoMenuItem acFormBar, acEditMenu, 2, , acMenuVer70
DoCmd.DoMenuItem acFormBar, acEditMenu, 5, , acMenuVer70 'Paste Append


Dim stDocName As String

DoCmd.SetWarnings False ' システムメッセージ非表示
stDocName = "追加クエリ"
DoCmd.OpenQuery stDocName, acNormal, acEdit
DoCmd.SetWarnings True ' システムメッセージ表示

' サブフォーム再クエリ
Me!REN.Requery

Exit_明細コピー_Click:
Exit Sub

Err_明細コピー_Click:
MsgBox Err.Description
Resume Exit_明細コピー_Click

End Sub

よろしくお願いいたします!

(昨日同じ質問をあげましたがカテゴリが間違っていたのでこちらにあげなおしました)

メインフォーム「MAIN」にサブフォーム「REN」を埋め込んでいます。

【メインフォームMAIN】
テーブル名:JIK
ID:事件ID

【サブフォームREN】
テーブル名:REN
ID:連絡先ID(・事件ID)

ボタンをクリックすると、メインフォームで表示させているレコードを複製させたいです。

以下を参考に、そのとおり(のつもり)に作ってみたのですが
(メインフォーム「MAIN」に「txtCopy事件ID」という名前のテキストボックスも作...続きを読む

Aベストアンサー

メインフォーム側の方は解決しました様で良かったです。

サブフォーム側のキー違反に関してですが、リンク先のURLの内容によると

メインフォーム→見積明細フォーム
 見積明細ID→オートナンバー型(主キー)
 見積品名→テキスト型
 ・・・

サブフォーム→工程明細フォーム
 工程明細ID→オートナンバー型(主キー)
 見積明細ID→数値型
 工程コード→テキスト型
 ・・・

とあります。これをそっくりそのまま質問者様の仕様に置き換えると

メインフォーム→MAIN
 事件ID→オートナンバー型(主キー)
 ・・・

サブフォーム→REN
 連絡先ID→オートナンバー型(主キー)
 事件ID→数値型
 ・・・

となるかと思います(一つ前の回答にも同じような事を書きましたが)
考えられるキー違反の原因としては、サブフォーム側で「事件ID」が主キー設定されていませんか?

リンク先のURLのイメージですと、例えば

【メインフォーム】
1 A みかん
2 C りんご
3 D ぶどう
項目名は左からID1(オートナンバー)、コード、品名とします。主キーは「ID1」

【サブフォーム】
1 1 A みかん 愛媛
2 2 C りんご 青森
3 3 D ぶどう 山梨
項目名は左からID2(オートナンバー)、ID1(数値)、コード、品名、産地とします。主キーは「ID2」

というレコードが各フォームにあるとして、メインフォームで2のりんごの項目を表示させてボタンを押すと

【メインフォーム】
1 A みかん
2 C りんご
3 D ぶどう
4 C りんご

【サブフォーム】
1 1 A みかん 愛媛
2 2 C りんご 青森
3 3 D ぶどう 山梨
4 2 C りんご 青森

という感じの動作になるかと思うのですが(間違っていたらお恥ずかしい限りですが。。。^^;)
この時サブフォームの「ID1」(=事件ID)は同じ値が複製されるので、主キーが設定されているとキー違反になってしまうかと思われます。

もしサブフォーム側の「事件ID」に主キーが設定されていたら、そちらは主キーを外して「連絡先ID」の方に主キー設定して下さい。
(勿論、メインフォーム側の「事件ID」は主キーでOKです)

他の原因だったらすみませんm(_ _)m

メインフォーム側の方は解決しました様で良かったです。

サブフォーム側のキー違反に関してですが、リンク先のURLの内容によると

メインフォーム→見積明細フォーム
 見積明細ID→オートナンバー型(主キー)
 見積品名→テキスト型
 ・・・

サブフォーム→工程明細フォーム
 工程明細ID→オートナンバー型(主キー)
 見積明細ID→数値型
 工程コード→テキスト型
 ・・・

とあります。これをそっくりそのまま質問者様の仕様に置き換えると

メインフォーム→MAIN
 事件ID→オートナンバー型(主キー)
 ・・...続きを読む

QAccessで別テーブルの値をフォームに表示したい

初めてのAccessで分からない事があり質問させてください。

<会社テーブル>
会社ID
会社名
住所

<社員テーブル>
会社ID
社員名
ソート番号

*1社に対し複数の社員レコードが存在

以上のようなテーブルがあるとします

現在「会社テーブル」を表形式で一覧表示しています
会社ID,会社名、住所とフィールドが並んでいるのですが、その後ろに「社員テーブル」のソート番号が一番若い社員名を表示したいと考えています(現状は番号関係なく表示させる方法すら分かりません)

色々いじくりまわしたのですが、初めてAccessをさわる事もあってよくわかりません

リレーション等でひっぱってくる事ができるのでしょうか?

どなたか教えて頂けませんでしょうか

何卒よろしくお願い致します

PS.Access2013で作成中です

Aベストアンサー

単純にテーブル[会社]のみでフォームを作成し、社員表示用テキストボックスを追加。そして、そのプロパティを表示し

コントロールソース=DBLookup("SELECT 社員名 FROM 社員 WHERE 会社ID=" & [会社ID] & " ORDER BY ソート番号")

これは、以下の標準モジュールに登録したユーザ関数 DBLookup()を使っています。これで、クエリを用意しなくても目的を達成できます。

さて、かかるユーザ関数を標準ライブラリに登録したくない場合、

1、"社員ソートクエリ"を作成します。

SELECT 社員.会社ID, 社員.社員名
FROM 社員
ORDER BY 社員.ソート番号;

2、コントロールソースに次のように書きます。

=DLookUp("社員名","社員ソートクエリ","会社ID=" & [会社ID])

http://office.microsoft.com/ja-jp/access-help/HA001228825.aspx

DLookup()については、マイクロソフトの解説を参照されてください。

【DLookup()の限界を破るにはVBAで同じ関数を作るしかない】

マイクロソフトの解説を読めば判りますが、ORDER BY 節を指定する引数が用意されていません。ですから、どうしても、"社員ソートクエリ"を作成するという手間が必要となります。そこで、SQL文を引数とするDBLookup()をVBAで書けば、その手間を省けるという算段になります。この辺りは、好みと趣味の問題。どっちでも良いと思います。そういうお断りをした上で DBLookup()を紹介しておきます。なお、ADOは、つぎのように参照設定しないと利用できません。

http://www.happy2-island.com/access/gogo03/capter00307.shtml

Public Function DBLookup(ByVal strQuerySQL As String, _
             Optional ByVal ReturnValue = Null) As Variant
On Error GoTo Err_DBLookup
  Dim DataValue
  Dim rst     As ADODB.Recordset

  Set rst = New ADODB.Recordset
  With rst
    .Open strQuerySQL, _
       CurrentProject.Connection, _
       adOpenStatic, _
       adLockReadOnly
    If Not .BOF Then
      .MoveFirst
      DataValue = .Fields(0)
    End If
  End With
Exit_DBLookup:
On Error Resume Next
  rst.Close
  Set rst = Nothing
  DBLookup = IIf(Len(DataValue & ""), DataValue, ReturnValue)
  Exit Function
Err_DBLookup:
  MsgBox "SELECT 文の実行時にエラーが発生しました。(DBLookup)" & Chr$(13) & Chr$(13) & _
      "・Err.Description=" & Err.Description & Chr$(13) & _
      "・SQL Text=" & strQuerySQL, _
      vbExclamation, " 関数エラーメッセージ"
  Resume Exit_DBLookup
End Function

単純にテーブル[会社]のみでフォームを作成し、社員表示用テキストボックスを追加。そして、そのプロパティを表示し

コントロールソース=DBLookup("SELECT 社員名 FROM 社員 WHERE 会社ID=" & [会社ID] & " ORDER BY ソート番号")

これは、以下の標準モジュールに登録したユーザ関数 DBLookup()を使っています。これで、クエリを用意しなくても目的を達成できます。

さて、かかるユーザ関数を標準ライブラリに登録したくない場合、

1、"社員ソートクエリ"を作成します。

SELECT 社員.会社ID, 社員.社員名
FR...続きを読む


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング