Microsoft Access 掲示板

非連結のテキストボックスデータを連結したい

10 コメント
views
4 フォロー

現在商品フォームの中に、サブ案件フォームを置いており、
サブ案件フォームでその商品を購入した案件をリスト表示しています。

その中で、商品フォームの項目に「最新購入日」を作成し、サブフォームの中の「購入日」フィールドから
一番新しい日を引っ張りたいと思っています。
そこで、コントロールソースとして
=DMax("購入日","T_案件","商品NO=forms![F_商品]![txt商品NO]")
と記載しております。

このデータを、「最新購入日」のテキストボックスに格納(連結データに)し、
別の場所でも利用したいのですがどのようにすればよいでしょうか。。

どんぐり
作成: 2020/09/05 (土) 11:33:06
最終更新: 2020/09/05 (土) 11:38:03
通報 ...
1
hatena 2020/09/05 (土) 12:08:38 修正

商品フォームのレコードソースのテーブルに「最新購入日」のフィールドは作成済みですか。
作成していない場合は作成してくださいね。

そこで、コントロールソースとして
=DMax("購入日","T_案件","商品NO=forms![F_商品]![txt商品NO]")
と記載しております。

これでも、最新購入日は表示されますが、
サブフォームでレコードを追加したり、購入日を編集しても、反映されませんよね。
反映された方がいいですよね。

サブフォームのフォームヘッダーかフッターにテキストボックスを配置して下記のように設定します。

名前 最新購入日
コントロールソース =Max([購入日])

メインフォームの最新購入日を表示するテキストボックスは、下記のように設定します。

名前 txt最新購入日
コントロールソース =[サブフォームコントロール名].Form![最新購入日]

これで、サブフォームで更新、追加して確定すると即反映されます。

これができたら、メインフォームの更新前処理のイベントプロシージャを下記のように記述します。

Private Sub Form_BeforeUpdate(Cancel As Integer)
    If Me!最新購入日 =  Me.txt最新購入日 Then
    Else
       Me!最新購入日 =  Me.txt最新購入日 
    End If
End Sub

これでテーブルに反映されます。

2
どんぐり 2020/09/07 (月) 23:28:57 0029a@1c915

ありがとうございました!ところで理解力がなく申し訳ないのですが、
わからない点があり、教えていただけませんでしょうか…

①VBA内の「Me!最新購入日」については「サブフォームコントロール名.Form!最新購入日」と
 しなくてよいのでしょうか。
②Me!最新購入日 =  Me.txt最新購入日 についてですが、
 式の左側に右側を代入するイメージだと思っていたのですが、この場合は
 Me.txt最新購入日  =  Me!最新購入日 にならないのでしょうか。

3

そちらのフォームの状況が分からないので、下記のようだと想定してコーディングしています。

メインフォーム
名前 商品フォーム
商品フォームのレコードソースのテーブル(商品テーブル?)に「最新購入日」フィールドがある。

サブフォーム
名前 サブ案件フォーム
レコードソース T_案件
T_案件 には「購入日」フィールドがある

①VBA内の「Me!最新購入日」については「サブフォームコントロール名.Form!最新購入日」と
 しなくてよいのでしょうか。

Me!最新購入日はレコードソースの「最新購入日」フィールドになります。

If Me!最新購入日 =  Me.txt最新購入日 Then
「最新購入日」フィールドの値と「txt最新購入日」テキストボックスの値が等しいか判定してます。
「txt最新購入日」のコントロールソースは=[サブフォームコントロール名].Form![最新購入日]ですので
サブフォームの最新購入日になります。
つまり、メインフォームの「最新購入日」フィールドとサブフォームの「最新購入日」が一致しているかどうかの判定です。

②Me!最新購入日 =  Me.txt最新購入日 についてですが、
 式の左側に右側を代入するイメージだと思っていたのですが、この場合は
 Me.txt最新購入日  =  Me!最新購入日 にならないのでしょうか。

「左側に右側を代入する」であってます。
IfのElse節に入ってますので、
メインフォームの「最新購入日」フィールドとサブフォームの「最新購入日」が一致していなかったら、
サブフォームの「最新購入日」をメインフォームの「最新購入日」フィールドに代入しています。
これでサブフォームの「最新購入日」とメインフォームの「最新購入日」は常に一致していることになります。

4
どんぐり 2020/09/15 (火) 08:53:53 0029a@1c915

詳しく教えていただき、ありがとうございます。
この件につきまして、最新購入日の他のフィールドをひっぱりたいのですがうまくいきません。
サブフォーム内にテキストボックスを作成し、コントロールソースに以下の式を入れましたが
「Name?」と表示される状況です。
コーテーションや「txt・・・」に変更したりと、苦戦しているのですがうまくいきません…

=DLookUp("案件NO",[Q_案件],"購入日='" & [最新購入日] & "'")

どこに問題があるのでしょうか??スミマセン…

5
hiroton 2020/09/15 (火) 09:19:38 49c70@f966d

内容細かく見てないけど
=DLookUp("案件NO",[Q_案件],"購入日='" & [最新購入日] & "'")

=DLookUp("案件NO","Q_案件","購入日=#" & [最新購入日] & "#")
かな?

適当なテキストボックスのコントロールソースにに「=[最新購入日]」としてみましょう。次に「=[Q_案件]」としてみましょう

6
どんぐり 2020/09/15 (火) 12:33:05 0029a@1c915

うまくいきました!すごいです。

や&やコーテーションの使い方がいつまでたっても難しく感じます。

何か参考になる良いサイトはないでしょうか…
(今回下記サイトを参考にしていたのですが、#の件がのっていませんでした)
https://pctips.jp/pc-soft/access-dlookup-howto2019/

7
hatena 2020/09/15 (火) 13:17:47 修正

引用符に関しては、下記が参考になると思います。

Access上のコード内で引用符(")と単引用符(')の使い分けについて - hatena chips

上記のリンク先でもいってますが、まずは、VBAコードとSQLコードは違う言うことを意識する必要があります。
まずは上記の解説を読んで理解してください。

そのうえで、

=DLookUp("案件NO","Q_案件","購入日=#" & [最新購入日] & "#")

この DLookup はVBAの関数です。それぞれの引数は、
第一引数 フィールド名またはフィールド名を含む式を文字列で指定
第二引数 テーブル名/クエリ名を文字列で指定
第三引数 抽出条件式を文字列として指定
抽出条件式はSQLのコードです。クエリのSQLのWHERE句に記述する式のことです。
それをVBAの文字列とします。

あと、コード中で、数値、文字列、日付を扱うときは、扱いが異なります。
数値はそのまま、文字列は引用符で囲む(上記のリンクを参照)、日付は # で囲む、
という決まりです。
これはVBAでもSQLでも同じです。

8
どんぐり 2020/09/15 (火) 17:20:07 f1ed8@111ea

ありがとうございます!所持している本にも理屈が載ってなかったので、すごく助かります。熟読します。

9
hiroton 2020/09/17 (木) 15:37:19 58418@f966d

知識が幅広く必要なためか、あまりうまいこと解説しているところはないですね。

VBAとSQL

VBAはプログラミング言語です。
SQLは構造化照会言語(データベースを扱うための所定の書式)です。

VBAにはSQLを実行する機能がありますが、実行そのものはデータベースエンジンに丸投げします。なので、「SQL構文を文字列で指示する」までがVBAで出来ることです。そして、この文字列がSQLの文法として正しいかどうかすらチェックしません。ダメだったらダメだったときにエラーだと返ってくるだけです

SQL構文の例

UPDATE T名簿 SET 小遣い = 小遣い + 1000 WHERE 氏 & ' ' & 名 = '鈴木 イチロー' AND 契約年 >= #2000/1/1#;

VBAでSQLを実行する例

CurrentDb.Execute "UPDATE T名簿 SET 小遣い = 小遣い + 1000 WHERE 氏 & ' ' & 名 = '鈴木 イチロー' AND 契約年 >= #2000/1/1#;"

入力ミスをしてみましょう
VBAでSQLを実行する例(入力ミス)

CurrentDb.Execute "UPDATE T名簿 SET 小遣い = 小遣い + 1000 WHERE 氏 & ' ' & 名 = 鈴木 イチロー' AND 契約年 >= #2000/1/1#;"

実行しようとするSQL構文

UPDATE T名簿 SET 小遣い = 小遣い + 1000 WHERE 氏 & ' ' & 名 = 鈴木 イチロー' AND 契約年 >= #2000/1/1#;

単独の文字列としか見ないVBAではわかりにくいですが、SQL構文を色を付けてくれるエディタでみると間違っていることが分かりやすいですね。

実際には様々な部分を変数にしたいとなると思うので、ワンステップ置いて内容を確認するようにするといいです

Dim strSQL As String

strSQL = "UPDATE T名簿 SET 小遣い = 小遣い + " & Me!小遣い増減 & " WHERE 氏 & ' ' & 名 = '" & Me!氏名 & "' AND 契約年 >= #" & Me!適用日 & "#"
Debug.Print strSQL '//SQL構文確認用
CurrentDb.Execute strSQL

&もあちこちに出ていますが、VBAでもSQLでも前後の文字列を連結するという役割をします。SQL構文を作るためのVBAの&なのか、SQLとして処理されるときの&(VBA上ではただの文字)なのか、これもコードの色分けがあるとわかりやすいと思います。

もちろん、SQLで処理するときでもただの文字として見たいということもあり得ます。

'//VBA
strWhere = "社名='P&G'"
--SQL
WHERE 社名='P&G'

#'

リテラルのデータ型を表す文字です。
リテラルとはコード内に直打ちされた値のことです。

Dim a
a = 9 / 3
'// a は変数
'// = / は演算子
'// 9 3 はリテラル

VBAではリテラルのデータ型によって
数値型 => 数値をそのまま
文字型 => 「"」で囲む ※「'」は使えない
日付型 => 「#」で囲む

(ACCESS)SQLではリテラルのデータ型によって
数値型 => 数値をそのまま
文字型 => 「"」または「'」で囲む
日付型 => 「#」で囲む

というように決まっています。

そしてこの(ACCESS)SQLでの「#」はかなりローカルな仕様です。
SQLとは単にそういった場合、本来、国際規格で決まっているモノで、それには日付型に「#」を使うルールはありません。そのため、SQLを勉強しようとしてもこの「#」についての解説はACCESSに言及しているようなところでしか見ることができません。

SQL構文を確認する

VBAならDebug.Printで実行直前の文字列を取得できます。フォームのテキストボックスなんかの場合はとりあえず「="購入日=#" & [最新購入日] & "#"」のように確認したい部分だけの式にするといいでしょう

後はそれで表示された文字列をコピーして色分け表示すればいいです。
この掲示板ならコードブロックを使うと色分け表示できます。(上の誤りなSQLの表示を見ると今一歩な感じ)
Webサービスを探してもいいでしょう(SQL Fiddle(sqlfiddle.com)とか)
※ローカルルールな「#」にどのように対応しているのかは気に掛ける必要があります

そもそものもとになるSQL構文はクエリデザインから作成するのも手です。
適当な抽出条件を設定したクエリを作って、表示できることを確認したあとSQLビューを確認すればもとになるSQLが作れます。あとは「適当な抽出条件」としたところを変数に置き換えていけば動的に変化するSQL文が作れます。
デザインビューからの表示を通すことによって、データ型による囲み文字の補完、型不一致のエラーのチェックなんかができます

10
どんぐり 2020/09/18 (金) 16:33:48 1d451@2d897

教えていただきありがとうございます!連休中にじっくり読みます。