Private Sub Form_Current()
If Me.NewRecord = True Then '新規レコードの場合はテキストボックスを操作不可にする
[btn_次レコード].Enabled = False
Else
[btn_次レコード].Enabled = True
End If
End Sub
Private Sub Form_Current()
If Me.NewRecord Then
Me.txb_何件中何件目.Value = Me.CurrentRecord & "/" & Me.Recordset.RecordCount + 1
Else
Me.txb_何件中何件目.Value = Me.CurrentRecord & "/" & Me.Recordset.RecordCount
End If
End Sub
Public Sub SetFlag()
Dim rs As DAO.Recordset
Dim strSQL As String
Dim pre社員No
CurrentDb.Execute "UPDATE Mtbl_所属歴 SET flg削除 = False WHERE flg削除 = =True;"
strSQL = "SELECT * FROM Mtbl_所属歴 ORDER BY 社員No, 開始日, 終了日;"
Set rs = CurrentDb.OpenRecordset(strSQL, dbOpenDynaset, dbFailOnError)
Do Until rs.EOF
If pre社員No <> rs!社員No Then
pre社員No = rs!社員No
rs.Edit
rs!flg削除 = True
rs.Update
rs.MovePrevious
rs.Edit
rs!flg削除 = True
rs.Update
rs.MoveNext
ElseIf 特定の名称が含まれる Then
rs.Edit
rs!flg削除 = True
rs.Update
End If
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
MsgBox "完了"
End Sub
Private Sub コンボ351_AfterUpdate()
With Me.Recordset.Clone
Do Until .EOF
.Edit
!suitei_tenko = Me!コンボ351
.Update
.MoveNext
Loop
.Close
End With
Me.Recalc
End Sub
SELECT
T1.社員No, T1.社員名, T1.所属
FROM
Mtbl_所属歴 T1
INNER JOIN
(SELECT
社員No, Min(開始日) AS Min開始日, Max(終了日) AS Max終了日
FROM Mtbl_所属歴
GROUP BY 社員No) Q1
ON T1.社員No=Q1.社員No
WHERE
T1.開始日>Min開始日 And T1.終了日<Max終了日;
Private Sub コンボ353_AfterUpdate()
Dim SQL As String
SQL = _
" UPDATE public_stb_ra_time_shokin_5 INNER JOIN public_stb_ra_tpc_sabun ON public_stb_ra_time_shokin_5.race_id = public_stb_ra_tpc_sabun.race_id SET public_stb_ra_tpc_sabun.suitei_tenko = " & [Me]![form]![コンボ_353].[value] & _
" WHERE (((public_stb_ra_time_shokin_5.hizuke)=" & [Me]![開催日].[value] & "));"
CurrentDb.Execute SQL
Me.Refresh
End Sub
ぱっと見ですが、
「T_住所1分割」の「住所1前半」「住所1後半」フィールドの値要求プロパティと空文字の許可プロパティはどうなっていますか?
これに対して、
これらの計算結果はどのような結果が取られますか?
各プロパティの設定によって、そのフィールドに「Nullは使えない」「空文字(
""
)は使えない」のような制限がかかります。それらのフィールドに使えない値を入れようとすると問題の警告が表示されます書式は最終的な表示の仕方を決めるものです。最終的な表示場所(今回の場合はレポート)で設定すれば十分です
ただ、同じデータをフォームで表示したい・レポートで表示したいなど複数用いることもあります。その場合、デフォルトの書式としてレコードソースの書式を用いるので、テーブルで書式を設定しておけば、基本的にその書式で表示する(後から変更もできる)という使い方もできます
既に指摘していますが、「書式をyyyy年mm月dd日として」いて、「『2024年3月1日』と表示されているのはおかしい」です。どこかで書式を使った何かが間違っています
画像から見える限りでは、一枚目の画像のクエリの最初のフィールド「入金日を日付でグルー…」が怪しいです
ここまで記述してたら回答付いたので以下略
おそらくクエリをウィザードで作成したのですね。
そのときに、「日付をグループ化する単位を選択してください。」で「日」を選択したのでしょう。
そうすると、日付は下記のような演算フィールドになります。
Format関数で標準の日付書式にしてますので、テーブルでの書式は無視されますね。
Format関数の返り値は文字列ですので、文字列としての並び順になりますのでそのような結果になります。
このフィールドの式を削除して、「開始日」にすれば日付順になるでしょう。
私としては、レポートの並び順は、レポートの方で「並べ替え」プロパティ、「グループ化と並べ替え」を設定してなければ、レコードソースの並び順になると認識してました。
優先度の高い順
「グループ化と並べ替え」
「並べ替え」プロパティ
レコードソースの並び順
(クエリの並び替え設定、テーブルのインデックス設定)
しかし、レポートの方で「並べ替え」なり、「グループ化と並べ替え」で並び順を指定した方が確実ですね。
新しくクエリを作り直してみたのですが、日付順に並びました。
色々と教えていただき、ありがとうございました。
テーブルのデザインです。 テーブルだと2024年03月01日となっています。
もともとはExcelデータをインポートしてテーブルにしていて、「入金日」を列に加えて
「日付」データを参照して入力をして使っています。
(「日付」を使いたいのですが、データ型を「日付/時刻型」にするとデータを消えてしまったので、
新たに列を作りました。)
書式の指定は必要ないのでしょうか。
「レポートでも」というよりは「レポートの指定のみ」が反映されます。レポート上で並び順を指定しなかった場合の並びは不定です
クエリ上での確認は、単にレポート上で並び順を指定した場合に、求めた並び順になるかどうかの確認です
画像を見る限りそうではないようですね
データが正しく日付型データで保存されているのであれば日付順に正しく並びます
型を指定しているだけで、正しいデータが保存されていないか、書式の設定の仕方が間違っています
特に「書式をyyyy年mm月dd日」と設定しているのにも関わらず「2024年3月1日」と表示されているのはおかしいですね。「mm」や「dd」としているので、0を詰めて2桁で表示(2024年03月01日)されていないとおかしいです
書式が適用できず、元のデータをそのまま表示しているのでしょう
大元のテーブルのフィールドは「日付/時刻型」になっていますか?また、そのフィールドの書式を変更する(書式なしにする)と、きちんと望んだ日付のデータが保存されていますか?
クエリでの指定とその結果になります。
レポートで並び替えたい場合は、レポートでも日付のところで昇順の指定をしないといけないという事でしょうか。
そのクエリを直接表示した場合は指定の並び順になっていますか?
また、レポートでの並びは、レポート上で並び順の指定が必要です
レポートの既定の並べ替え順序を定義する
ご回答ありがとうございます。
データ型を「日付/時刻型」に設定し、書式をyyyy年mm月dd日としています。
日付フィールドでの並び替えはクエリで「昇順」に設定していますが、1日から並びませんでした。
設定方法など間違っているでしょうか。 宜しくお願いいたします。
日付フィールドのデータ型は日付/時刻型になってますか。
日付フィールドで並び替えを設定していますか。
原因究明は地道にやるしかないのですね・・・
Recalc、Refresh等を追記したところ、正常に表示されるようになりました!
ありがとうございます。
私の作成したサンプルにそのコードを追加しても、問題なく動作します。
問題のフォームと同じテーブルをレコードソースとするシンプルなフォームを作成して、
質問のテキストボックスとコマンドボタンを配置して、症状がでるか確認してみてください。
そこから、問題のフォームと同じになるように一つずつプロパティ設定やコードを追加していって、その都度、動作確認して、症状が発生する直前に変更、追加したものが、原因ということになります。
面倒ですが、原因追及するにはそのぐらいしかないでしょう。
ちなみに、前回の回答で提案した方法は2つとも効果がありませんでしたか。
回答ありがとうございます。
私も簡素なサンプルを作成してみましたが、正常に値を表示できました。
フォームのレコード移動時イベントで、新規レコードなら次レコードボタン(+いくつかのテキストボックス 下記コードでは省略)を使用不可にするコードを書いています。
これが何かしらCurrentRecordの値取得に影響を及ぼしている可能性はありますか?
当方でシンプルなサンプルを作成して確認してましたが、症状は確認できませんでした。
コマンドボタンで移動するごとに正しいレコード番号か表示されます。
コントロールの再計算のタイミングがずれている感じですね。
下記のように移動後に再計算させるとで改善されないですか。
あるいは、コントロールソースは空欄にしておいて、レコード移動時で代入するとか。
画像の解像度が低いので詳細が読み取れないので推測ですが、ご希望のことは下記のようなことでしょうか。
画像の左は集計クエリで縦に並んでいる。
それをクロス集計クエリで画像の右のように横に展開するようにする。
年月フィールドが毎年変わるので、それをレポートにする場合、作り直しになるのを、なんとかしたい。
だとしたら、下記のリンク先が参考になると思います。フォームになってますが、レポートでもそのまま応用できます。
列名が変化するクロス集計クエリと連結するフォーム - hatena chips
このような大雑把な説明では、回答しづらいです。
まず、勤怠システムから出力されるCSVのフォーマットを説明してください。
数行のサンプルを提示してもらえるとなおいいです。氏名などの情報はマスキングしておいてください。
それをアクセスのテーブルに取り込むことになると思いますが、現状のテーブルのフィールド構成を提示してください。
「翌月には新しいフィールドが追加されるので、」とのことですが、データベースではこのような設計にはしないので、テーブル設計から変更する必要があると思われます。
「その月の時間が入力される」とは具体的にどのようなことでしょうか。
条件はどこから取得するのかとか、どのようなデータをどこに入力するのかとか、あいまいすぎてイメージが湧きません。
まずは、CSVデータと、現状のテーブル設計の説明をお願いします。
すみません、自己解決できました。
ですね。
SQLで大分改善はしました。が、ちょっと待ち時間がストレスに感じるくらいです。
hatenaさまにいただいた、DAOでループ処理する方法でゆきたいと思います。
コードを一見して動きは理解できました。
rs.MovePreviousで1レコード前に戻るというのもできるのですね。
考えつきもしませんでした、勉強になりました。
何かを参照する場合は、「コードの実行場所」と「コードの実行場所から見た操作したい相手の場所」を常に意識することが大事です。
すべて無視して、ACCESS本体から見た「
Forms!~
」という記述も可能ですが、hatenaさん指摘のように、「コードの実行場所自身=>Me
」や、「サブフォームからみた親フォーム=>Me.Parent
」、「親フォームから見たサブフォーム=>Me![サブフォーム名].Form
」等の参照方法を覚えるとコードが簡素に記述できますまた、参照に用いる場合の
[]
使い方も覚えましょう。これは、基本的に「名前」を指定するときに用いる記号です。ACCESS本体が持つ機能(キーワード)に使うことはできませんたとえば、「天候」を保存するために用意したフィールド「
suitei_tenko
」を指定する場合に、[suitei_tenko]
等記述します。「フォームに読み込んだそれを参照する」ならのようになります
通常「
Me
」とは、コードを実行したオブジェクトを参照するキーワードで何かの名前ではありません。[Me]
と記述した場合、「Me
」と名前を付けた何か(フィールドとか、テキストボックスとか)を参照する記述となります。そのような「何か」が無ければ参照先が見つからないというエラーが発生しますまた、
[]
は省略可能な記述で、ACCESS上(フォームやレポート等)で記述すると自動で付加されますが、VBAで記述する場合は、なるべく省略したほうがコードがすっきりします「省略できない場合」もあるので、より深い知識が必要になったら調べてみると良いでしょう
あぁ、コードがめちゃくちゃでしたね。ごめんなさい
hatenaさんが正しいコード例を提示してくださっているのでそちらを参考にしてください
クエリを使うか、レコードセットを操作するかについては、フォームに読み込んだレコードを操作するのであれば、圧倒的にDAOによるレコードセットの操作のほうが楽だと思います
開いたフォームがすでにレコードセットを開いているので、よくあるレコードセットを扱うための魔法の言葉が不要で、
With
ステートメントの活用により余計な変数も不要になるのでフォームのレコードセットを操作する方法はいくつかあります。(hirotonの回答がめちゃくちゃなのも、これらを適当に組み合わせてしまっているからです)
DoCmd
によるフォームの操作ACCESSの機能を使ってフォームを見たまま操作する例です。見たまま、レコードを移動させながら操作するので、
suitei_tenko
もMeからの参照で現在のカレントレコードのフィールドの値を修正しますレコードセットの操作と異なり、レコードが無い場合の操作を行うとエラーが発生するので、それようの対策が必要です
「マクロ」で作る場合の理論をそのままVBAでコードにするとこんな感じでしょう
Me.Recordset
を操作表示しているフォームそのもののレコードを扱います。レコードセットのレコードを移動させると、フォーム上のレコードも移動するので、レコードの移動だけレコードセットを操作して、レコードの編集はフォーム上のコントロールを操作するとかいう訳の分からないコードを組むこともできます。(コードが短くなるだけで大したメリットはない)
Me.RecordsetClone
を操作フォームに読み込まれているレコードセットを直接操作します。ただし、表示中のレコードは移動しません。Meによる参照と、レコードセットからの参照で、参照しているレコードを別々に持つことになります
Me.Recordset.Clone
を操作(コードは省略)
全く同じレコードセットを新しく生成します
新規でレコードセットが生成されるので、常にレコードセットの先頭にカーソルがある状態のレコードセットになります。(
DoCmd.GoToRecord
やMoveFirst
のような、全件を操作するための準備がいらない)新規でレコードセットを生成しているので、閉じる処理(
Close
)が必要フォームとは関係ないレコードセットを操作するので、フォームに反映させる処理(
recalc
/refresh
/requery
)が必要データベースなので履歴データは基本は削除しない運用が望ましいですね。
ワークテーブルを使うのなら、上記の集計クエリを含むクエリを追加クエリにして追加すればすみます。
フラグフィールドを追加してそれを更新するなら、EXISTSサブクエリを使用した更新クエリにすることになりますが、
自分がするなら、前回の質問でも回答しましたが、VBAでレコードセットを回して更新する方法をとります。
SQLでいくか、VBAでいくかは、得意不得意があると思いますので、好みでいいと思います。
ご回答ありがとうございます。
EXISTSを使った相関サブクエリはJOINに比べて劣るのですね。勉強になります。
履歴データなので基本的には消せないのですが、
ワークテーブルを使って削除するか、もしくはフラグを立てて読み飛ばすかということを
したいなと。いずれにしても更新を想定しています。
となると、インデックスを貼ってEXISTSですか。まずは試してみます。
開始、終了日の条件はHAVINGになるのですね。勉強になりました。
それでも重いようであれば、この方法を採用してみます。
>hatenaさんの回答>> 2のサブクエリ Q1 の結果セットを
>一旦テンポラリテーブルに格納するといいでしょう
SQLをゴリゴリ書スキルがなく、更新不可となってしまうクエリを一時テーブルに書き出して、
Delete、Updateなどを行うとかはよく使っていました。
ありがとうございます。フォームのレコードセットを更新していく方法で、見事できました。期待以上です。しかし、Hatenaさんの手にかかれば何でも魔法のように解決しちゃいますね。いつもありがとうございます。書いていただいたレコードセットについての記事も読んで勉強します。
Accessは( Microsoft謹製のDBMSでは )
相関サブクエリのパフォーマンスがJOINに比べて劣る印象はありますね
しかしながら、Access-SQLにおいて
という場合、
つまり、UPDATE文やDELETE文を発行するケースでは
FROM句やJOIN句に sum, max, min といった集計関数を含めることは出来ません
( 利用できるのは、パフォーマンスが悪いD系の定義域集計関数だけ )
そのため、hatenaさんのアドバイスにあるとおり適切にINDEXを設定した上で
以下のようなSQLを発行するといいでしょう
結果セットとパフォーマンスが確認できたら
SELECT → DELETE に変更し
の条件も付与して下さい
なお、上記の相関サブクエリでも
という場合は
hatenaさんの回答>> 2のサブクエリ Q1 の結果セットを
一旦テンポラリテーブルに格納するといいでしょう
フォームのレコードセットはDAOレコードセットなので、下記あたりを参考に学習してください。
VBA DAO レコードセット 更新 - Google 検索
フォームのレコードセットについては、下記で詳しく解説しています。
フォームの Recordset, RecorsetClone, RecordSet.Clone の違いとは? - hatena chips
意味があるのかしら?例えば、年度毎に保管期間5年間して過ぎたら削除する、みたいな感じじゃダメなの?
コンボ351 というのはサブフォームにあるのですよね。
ならば、hirotonさんが提案されたフォームのレコードセットを更新していく方法がいいと思いますよ。
更新クエリで、サブフォームに記述するコードなら、Me(サブフォーム自身) と Parent(親フォーム) を使えば、
ややこしい参照式を使う必要はないです。
追伸 それとフォームのレコードセットを更新する方法のほうがよいのかもしれないですが、そっちの理屈はまったくわけがわからないです。
早速返信していただきありがとうございます。恥ずかしいですけど、アップした画像のようなフォームになっています。親フォームがF_T0指数評価用で、サブフォームが埋め込み47またはF_TP指数です。(サブフォームを指定するときはどっちを書いたらいいものかいつも迷いますが、記憶では埋め込み47を書くのが正しいのではないか、と)。親フォームにあるテキストボックスの[開催日]を見て、テーブルの該当箇所にコンボボックスの選択値=天気を入力しようと思ってます。が、できません。Formが見つかりません、というメッセージが出てきます。よろしくお願いします。
Private Sub コンボ351_AfterUpdate()
Dim SQL As String
SQL = "UPDATE public_stb_ra_time_shokin_5 INNER JOIN public_stb_ra_tpc_sabun ON public_stb_ra_time_shokin_5.race_id = public_stb_ra_tpc_sabun.race_id SET public_stb_ra_tpc_sabun.suitei_tenko = " & [Forms]![F_T0指数表示用]![埋め込み47]![Form]![コンボ351].[Value] & "WHERE (((public_stb_ra_time_shokin_5.hizuke) = " & [Forms]![F_T0指数表示用]![開催日].[Value] & "));"
CurrentDb.Execute SQL
Me.Refresh
End Sub
EXISTSを使った相関サブクエリは、基本的に遅いです。
相関(サブクエリからメインを参照する)を利用しない方法を検討しましょう。
下記でどうでしょう。
これでもまだ遅いなら、
社員No、開始日、終了日 にインデックスを設定してください。
[社員No]の値が同一であるグループごとに、ということでしょうか。
VBAでクエリを動的に生成し実行する場合、「クエリを実行する」という命令を記述する必要があります。
DoCmd.RunSQL メソッド (Access)
Database.Execute メソッド (DAO)
※クエリ(SQL構文)そのものの正否は見ていません
「フォームに表示されている全データを更新したい」のであれば、フォームのレコードセットを更新していく方法もありだと思います
hatenaさん、ありがとうございます。
確かに何度も読込が繰り返されている様な
状態でしたので、仰っていることは
的を得ているかもしれません。
とても勉強になりました。
ありがとうございます。
書籍の作例は、同じような形式で真似るに留め、
経験を積まれたお二方のアドバイスに従い、
今回は連結で進行させた方が良さそうですね。
ありがとうございます。
りんごさんがピタゴラスイッチという表現をされてますが、そういう現象が起きているのでは?
要するに、連鎖反応で再読込が繰り返されているということではないかと。
内部動作は1ユーザーからは知る由もないので、あくまで推測ですが。
あるコントロールの値を参照して、さらにそれをサブフォームのリンクフィールドのプロパティから参照して、サブフォームデータにフィルターがかかる(再読込される)、それが複数のサブフォームで発生する、それが循環参照のような感じになっている・・・・
このような複雑な参照関係は、思わぬ動作の原因になるので、避けた方がいいというのが、私の経験則です。
りんごさん、ありがとうございます。
ご提案して頂いた方法は
既に出来上がっております。
確かに連結で同じように作ると、
質問にあるような現象は現れません。
今回質問に至った経緯は、書籍に掲載されている
メインに対して一つのサブがある作例を参考に、
サブを三つに増やした結果、現れた現象について、
考えられる原因を探りたくなったからです。
ピタゴラスイッチをやめて、メインフォーム連結レコードソースをきちんと設定してメインサブを組めばいいんじゃない?
hatenaさん、ありがとうございます。
点滅は、その状態が維持されます。戻りません。
テーブルはローカルです。
宜しくお願いします。
「マウスポインタが砂時計になって点滅する」というのは、ずっとその状態が続いているのか、しばらくしたら通常の状態になるか、どちらでしょう。
また、しばらくしたら通常に戻る場合は、どのくらいの時間で戻りますか。
また、テーブルはローカルテーブルですか、それともネットワーク上のデータベースからのリンクテーブルですか。
どうにか動くようになりました。でも理由はわかりません。お騒がせしました