Access (VBA)

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

 
(Windows 7全般 : Access 2003)
サブフォームのクエリにコピペした時のイベント(VBA)
投稿日時: 18/03/05 16:35:42
投稿者: pao

あまりAccessの知識が無いので分かりにくければ申し訳ないです。
 
フォームとサブフォームがあって、サブフォームはクエリから読み込ませ、
メインフォームのidで連動させてます。
サブフォームの入力項目に『品名』『単価』『個数』『小計』『入力初期時小計』
『注文日(他5項目)』があります。
『小計』は自動計算で[単価]*[個数]としてます。
このサブフォームからデータベースに入力させたいのは『小計』以外です。
VBAとイベントの「個数_AfterUpdate」や「個数_Change」を使い、『入力初期時小計』が
未入力であれば『小計』の値を『入力初期時小計』にコピーしています。
また、『注文日(他5項目)』にメインフォームからコピーしています。
1つずつ入力するのであれば問題なく動くのですが、
このサブフォームにエクセルから『品名』『単価』『個数』のデータ貼り付けを
複数行実施した場合、『注文日(他5項目)』にメインフォームは問題なく自動的にコピーしてくれるのですが、
『入力初期時小計』はゼロのままになります。
おそらく、貼り付けた瞬間に『注文日(他5項目)』はコピーされますが、
この段階では『小計』が計算されていないのでゼロとなるのだと思います。
試しにVBAで『入力初期時小計』を[単価]*[個数]としてみましたが同じくゼロのままです。
BeforeUpdate、AfterInsertも試しましたがダメでした。
 
@コピー貼り付けでも動作させるためにはどうすれば良いのでしょうか?
 
A難しいのであれば手動で貼り付ける方法は無いでしょうか?
イメージ的にはDCountで同一ID数を調べれば貼り付けた行数がわかりますので、
NEXT処理を行数だけ繰り返して↓みたいなイメージで行けないでしょうか?(iが行数)
 Form_サブフォーム.入力初期時小計(i)= Form_サブフォーム.単価(i) * Form_サブフォーム.個数(i)
 
よろしくお願いいたします。

回答
投稿日時: 18/03/05 17:48:59
投稿者: Suzu

引用:
サブフォームの入力項目に『品名』『単価』『個数』『小計』『入力初期時小計』
『注文日(他5項目)』があります。
『小計』は自動計算で[単価]*[個数]としてます。

 
 
『品名』『単価』『個数』『入力初期時小計』『注文日(他5項目)』
これらは、コントロールのコントロールソースに
サブフォームの元となるクエリのフィールド名が入っている連結コントロールで良いのかな?
 
で、『小計』 が、コントロールのコントロールソースに、
【[単価]*[個数]】を指定している演算コントロール
 
 
引用:
また、『注文日(他5項目)』にメインフォームからコピーしています。

 
メインフォームから??
メインフォームサブフォームに同じ内容を持っているのですか?
何のためにその様な事が必要なのでしょう。
 
引用:
フォームとサブフォームがあって、サブフォームはクエリから読み込ませ、
メインフォームのidで連動させてます。

 
なのですから、IDで連結すれば、クエリで得られる内容ですよね?
 
もしかして、メインフォームのVBA処理で Excelのデータをコピペしてきていると言いたいのかな。
 
 
これを、このタイミングで実行しなければいけない理由は何でしょうか?
閉じる時に
 
更新クエリにて、『入力初期時小計』 が Nullのレコードは、
[単価]*[個数] の値を代入する更新クエリを発行する事では代用できないのですか?
 
Excelから貼り付けた後に、確実に処理したいのであれば、
サブフォームの レコード移動時 カレント イベント で、
NewRecord以外、『入力初期時小計』がNullの場合 の判定を行い、
[単価]*[個数] を代入しては?

回答
投稿日時: 18/03/06 10:37:05
投稿者: sk

引用:
フォームとサブフォームがあって、サブフォームはクエリから読み込ませ、
メインフォームのidで連動させてます。

引用:
『小計』は自動計算で[単価]*[個数]としてます。

・サブフォームのレコードソースである選択クエリに
 [単価]*[個数] という式の結果を返す演算フィールド[小計]があり、
 そのフィールドをコントロールソースとする連結テキストボックス[小計]が
 サブフォームの詳細セクション上に配置されている。
 
・=[単価]*[個数] という式がコントロールソースに
 設定された演算テキストボックス[小計]が
 サブフォームの詳細セクション上に配置されている。
 
・数値型のフィールド[小計]をコントロールソースとする
 連結テキストボックス[小計]がサブフォームの詳細セクション上に
 配置されており、いずれかのコントロールの何らかのイベントで
 [単価]*[個数]の結果を[小計]に代入するコードが実行される
 ようにしている。
 
上記のどの方式に該当するのかが不明瞭です。
 
引用:
VBAとイベントの「個数_AfterUpdate」や「個数_Change」を使い、『入力初期時小計』が
未入力であれば『小計』の値を『入力初期時小計』にコピーしています。

実際にフォームモジュールに記述されているコード
明記されることをお奨めします。
 
引用:
このサブフォームにエクセルから『品名』『単価』『個数』のデータ貼り付けを
複数行実施した場合、『注文日(他5項目)』にメインフォームは問題なく
自動的にコピー
してくれるのですが、『入力初期時小計』はゼロのままになります。

例えば[入力初期時小計]に対する[小計]の値の代入処理を
[個数]の Change イベントでしか行なわれていない
のであれば、つじつまとしては合いますが。
 
引用:
おそらく、貼り付けた瞬間に『注文日(他5項目)』はコピーされますが、
この段階では『小計』が計算されていないのでゼロとなるのだと思います。

それは前述のどの方式を採用されているかにもよるでしょう。

投稿日時: 18/03/06 10:46:35
投稿者: pao

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

引用:
メインフォームから??
メインフォームサブフォームに同じ内容を持っているのですか?
何のためにその様な事が必要なのでしょう。
なのですから、IDで連結すれば、クエリで得られる内容ですよね?

仰りたいことはよく分かります。
このAccessは随分昔に業者に作らせ、その後色々な人がさわり
それぞれが欲しいデータを取るためにぐちゃぐちゃになってます。
今、どこか触ると他で使われているデータに影響が出るため、
時間をかけて全体を見直さないとダメですが、
さわり始めたばかりなのでこれからボチボチ見ていきたいと考えてます。
 
 
引用:

もしかして、メインフォームのVBA処理で Excelのデータをコピペしてきていると言いたいのかな。

コピペは手動でエクセルから『品名』『単価』『個数』のみを張ります。
この時、エクセル側で『入力初期時小計』を計算し張ればいい話なのですが、
色々事情があり、それが出来なくAccessから実施することになってます(手入力で)。
 
引用:
更新クエリにて、『入力初期時小計』 が Nullのレコードは、
[単価]*[個数] の値を代入する更新クエリを発行する事では代用できないのですか?

まだ始めたばかりで更新クエリがある事自体知りませんでした。
教えて頂いた通り更新クエリでほぼ解決したのですが、
データを更新表示したいのでイベントで.Form.Requeryを利用したのですが、
『この操作はトランザクションには実行出来ません』
で、実施出来ず、仕方なく手動でメインフォームから実施することで妥協しました。
お陰様で解決出来、ありがとう御座いました。
 
解決はしたのですが、もう一点、出来れば教えて頂きたいのですが、
 
引用:
Excelから貼り付けた後に、確実に処理したいのであれば、
サブフォームの レコード移動時 カレント イベント で、
NewRecord以外、『入力初期時小計』がNullの場合 の判定を行い、
[単価]*[個数] を代入しては?

この場合、入力初期時小計=[単価]*[個数]とすると、一番上の1列目しか計算してくれません。
2行目以降を書き換えるにはどうすれば良いのでしょうか?

投稿日時: 18/03/06 10:49:30
投稿者: pao

skさんもありがとう御座いました。
書き足らぬ所ばかりで申し訳ありません。
 
ほぼ解決出来ましたのでお礼のみ書かせて頂きます。

回答
投稿日時: 18/03/06 11:10:40
投稿者: Suzu

引用:
このAccessは随分昔に業者に作らせ、その後色々な人がさわり
それぞれが欲しいデータを取るためにぐちゃぐちゃになってます。

 
 
触りたくないやつですね。
 
sk さんの アドバイスは質問はスルーですか。
要は動く様になったからとりあえずいいや。と。。
 
触りたくなくなる理由を更に 一つ上乗せしたのですね。
 
 
引用:
入力初期時小計=[単価]*[個数]とすると、一番上の1列目しか計算してくれません。

レコード移動時イベントですよ?
 
フォーカス のあるレコードのみの操作 です。
このイベントで、全データ更新したいなら、手動で、全データへフォーカスを移動させて下さい。
 
VBAを使えば 色々できますが、
メンテナンスできそうもないので辞めておいた方が良いでしょう。

投稿日時: 18/03/06 12:53:03
投稿者: pao

せっかく回答頂いているのに失礼しました。
 

引用:

@・サブフォームのレコードソースである選択クエリに
 [単価]*[個数] という式の結果を返す演算フィールド[小計]があり、
 そのフィールドをコントロールソースとする連結テキストボックス[小計]が
 サブフォームの詳細セクション上に配置されている。
 
A・=[単価]*[個数] という式がコントロールソースに
 設定された演算テキストボックス[小計]が
 サブフォームの詳細セクション上に配置されている。
 
B・数値型のフィールド[小計]をコントロールソースとする
 連結テキストボックス[小計]がサブフォームの詳細セクション上に
 配置されており、いずれかのコントロールの何らかのイベントで
 [単価]*[個数]の結果を[小計]に代入するコードが実行される
 ようにしている。
上記のどの方式に該当するのかが不明瞭です。

 
便宜上番号を振らせて頂きましたが、Aで実施してました。
@も試しましたが変わらず。
 
 
引用:
実際にフォームモジュールに記述されているコード
明記されることをお奨めします。

 
Private Sub 個数_Change(Cancel As Integer)
   注文日(他5項目) = Form_メインフォーム.注文日(他5項目)
 '同じように他5項目
   入力初期時小計 = 小計
   '入力初期時小計 = = 単価 * 数量 でもダメ
End Sub
 
同じようにChangeの部分をBeforeUpdateやAfterUpdateにして試しました。
 
今は、更新クエリを作成し、
    DoCmd.SetWarnings False
    DoCmd.OpenQuery "更新クエリ名"
    DoCmd.SetWarnings True
を、追記して使って、一応動作してます。
ただ、再読み込みしないと表示してくれないので、メインフォームから更新ボタンを作って、
Forms![メインフォーム]![サブフォーム].Form.Requery
と、言った感じで更新すれば表示されてます。

回答
投稿日時: 18/03/06 15:49:46
投稿者: hatena
投稿者のウェブサイトに移動

pao さんの引用:

Private Sub 個数_Change(Cancel As Integer)
   注文日(他5項目) = Form_メインフォーム.注文日(他5項目)
 '同じように他5項目
   入力初期時小計 = 小計
   '入力初期時小計 = = 単価 * 数量 でもダメ
End Sub
 
同じようにChangeの部分をBeforeUpdateやAfterUpdateにして試しました。

 
エクセルのデータを追加貼り付けしているのてしょうか。
 
だとしたら、下記のコードでいいかと思います。
 
'サブフォームの更新前処理
Private Sub Form_BeforeUpdate(Cancel As Integer)
    If Me.NewRecord Then
        Me![注文日(他5項目)] = Parent![注文日(他5項目)]
  '同じように他5項目
        Me!入力初期時小計 = Me.小計
    End If
End Sub
 
ちなみに、上書きコピー時にも対応したいなら、上記のIf文を削除してください。
 
レコードコピー時にはコントロールのイベントは発生しないが、フォームの更新前処理は発生する。よって、フォームの更新前処理で処理すればOK。
 
 
ただ、疑問なのは、これが必要なのかということ。
Changeイベントで更新しているなら、入力初期時小計 と 小計 は基本的に同じはず、同じものを格納する必要はあるの?
(このフォーム以外で編集することがあり、初期値として残しておきたいということならありですが)
 
また、メインフォームのデータを転記してますが、これもメインフォームと同じデータをわざわざ格納する必要はないと思います。
 
下記の状況でしかたなくしているのだとしたらしょうがないですが。
 
pao さんの引用:

このAccessは随分昔に業者に作らせ、その後色々な人がさわり
それぞれが欲しいデータを取るためにぐちゃぐちゃになってます。
今、どこか触ると他で使われているデータに影響が出るため、
時間をかけて全体を見直さないとダメですが、
さわり始めたばかりなのでこれからボチボチ見ていきたいと考えてます。

投稿日時: 18/03/06 18:05:10
投稿者: pao

hatenaさま、ありがとう御座いました。
色々組み合わせて実施したつもりだったのですが…。
↓でうまくいきました。

引用:
'サブフォームの更新前処理
Private Sub Form_BeforeUpdate(Cancel As Integer)
    If Me.NewRecord Then
        Me![注文日(他5項目)] = Parent![注文日(他5項目)]
  '同じように他5項目
        Me!入力初期時小計 = Me.小計
    End If
End Sub

 
Me.NewRecordも勉強になりました。
エクセルでVBAを少しだけ触った程度の知識しか無いため、色々勉強になります。
 
 
ただ、疑問なのは、これが必要なのかということ。
Changeイベントで更新しているなら、入力初期時小計 と 小計 は基本的に同じはず、同じものを格納する必要はあるの?
(このフォーム以外で編集することがあり、初期値として残しておきたいということならありですが)
また、メインフォームのデータを転記してますが、これもメインフォームと同じデータをわざわざ格納する必要はないと思います。

その通りなのです。
重複したデータですのでクエリでなんとでも出来るのですが、
色々な方が触っていまして1つ消すと必要なデータが得られなくなるようです。
1つ1つ整理して置き換えていくしか無いかと思っているのですが、
現行、とりあえず今あるデータ内でムダに手打ちしている作業を減らしたくて変更しようとしていましした。
全部直せば不要になるのかもしれないですが、現行はすごく助かりました。
ありがとう御座いました。
 
Suzuさま、SKさま
 
ありがとう御座いました。
回答締めさせて頂きます。