Microsoft Access 掲示板

views
4 フォロー
6,283 件中 3,681 から 3,720 までを表示しています。
2
nokonoko 2021/05/17 (月) 17:30:00 653a6@54883

ご回答ありがとうございます。基本的なやり方は間違えていないようです。
差し支えなければ、Hatena様の最後のコードについて説明いただけないでしょうか。
複数のテーブルをこのif~nextでリンクできるのでしょうか

Private Sub Form_Open(Cancel As Integer)
    Dim dbs As DAO.Database
    Dim tdf As DAO.TableDef

    Set dbs = CurrentDb
    For Each tdf In dbs.TableDefs

        If tdf.Connect Like "*データーベース1.accdb*" Then
            If tdf.Connect Like "*PWD=1234*" Then 
                Exit For
            Else
                tdf.Connect = _
                "MS Access;PWD=1234;DATABASE=C:\test\データベース1.accdb"
                tdf.RefreshLink
            End If
        End If
    Next tdf

    dbs.Close: Set dbs = Nothing

End Sub
1
りんご 2021/05/17 (月) 16:48:14 48103@0e907

下記サイトの回答コメントにあるのが、一般的な方法ではないでしょうか。

Access2013 リンクテーブルのパスワード設定について
リンク先のaccdbファイルにパスワードを新規設定又は変更を行った場合、リンク元のaccdbでパスワードを再設定する事は可能でしょうか? 例) データーベース2.accdbに データーベース1.accdb のTBL1をリンクテーブルとして作成(データベース1.accdbにはパスワード未設定) その後にリンク先であるデータベース1.accdbにパスワードを設定した場合、
microsoft

さらに、もっとも一般的な方法があれば、誰か補足をお願いします。

2
nokonoko 2021/05/17 (月) 16:07:21 653a6@54883

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

実は事業所が離れており、私がネットワークはいることができていない中でエラーが出てしまったのです。
現地はランタイムで動いていて、前述のプログラムでリンクをくっつけなおしていたのですが、うまくいかないようで。

私がいなくても、永続的に事業所内のデータとリンクできるようにしなくてはならないのですが。

この質問は立て直します。ありがとうございました。

15
だいふくもち 2021/05/17 (月) 13:58:32 修正

追記です。
メインフォームを新しく作り直したところ、消える現象はなくなりました!
プロパティの設定を新旧フォームで見比べてみたのですが、特に差異もなく…
原因を突き止めることができましたら、またご報告させていただきたいと思います。

14
だいふくもち 2021/05/17 (月) 11:19:51

>hatena様
ご回答とご指摘いただきありがとうございます!とても参考になりました!
Forループ内でカウンター変数を使用しない方が良いというのは知りませんでした…
例文をいくつか調べてみましたが、確かにカウンター変数を途中で変更されている方はおりませんでした。
ご法度というのは、For文にカウンター変数を変更する分岐を入れてしまうと、
煩雑になり可読性が落ちるからでしょうか?

また、コントロール名ではなく、フィールド名を指定するということですが、
こちらの理由をお伺いしてもよろしいでしょうか…?
個人的には、コードを見返した際に分かりやすく管理しやすいかな…
と思ってコントロール名を分かりやすい名前に変更し、指定していたのですが、
テーブルにデータを追加する場合などは、テーブルのフィールド名を指定しておかないと
後で問題になったりするのでしょうか?(見かける例文はコントロール名での指定が多い気がしたので…)

教えていただいたコードに変更しましたが、同じ症状が出てしまいます…
サブフォームをもう一度作り直してみましたが、結果は同じでした。
同じような症例がないか、もっと調べてみたいと思います。
(せっかくたくさんアドバイスいただいたのに解決できず申し訳ありません…)

18

適当にエラーが出るプロパティを設定してみたら同じエラーメッセージ出ませんでした。多分原因は

ArrayListSort関数も省略しているので適当な場所に入れておいてください

こっちのほうですね。

完全なコピペ

で必要な関数を消してしまったんでしょう。開く時(Report_Open)ではArrayListSort()使ってないのでエラーメッセージが残念な感じですがよくあることなので・・・

1
りんご 2021/05/17 (月) 08:34:02 48103@0e907

フロントエンドを開いて、リンク情報がどうおかしくなっているかを確認するのは?

8
どんぐりず 2021/05/17 (月) 00:26:57 修正 0029a@1c915 >> 5

ありがとうございました!
>確認メッセージが出る出ないは、DoCmd.SetWarningsのコードがどこかにありませんか?

こちらを参考に、改めて確認したところ
自分の環境では確認メッセージを出さないように設定しており、
他の環境では設定してもらうか、マクロ、VBAでの制御が必要と知りました。
VBAで制御したところ、メッセージが出なくなりました。

大変助かりました。ありがとうございました。

同じ悩みの方のため、参考サイトのリンクを貼っておきます。
AccessVBAでクエリ実行時の確認メッセージを完全に非表示にする方法

3
りんご 2021/05/16 (日) 23:46:37 48103@0e907 >> 1

 ごめんなさい、Dsum動作比較のサイトを紹介しましたが、中身をよくわかっていませんでした。ちょうど使ってみて、使い勝手がいいじゃんと思ったんですけど、重くなりそうになったら要変更ですね。
 下記、Hatenaさんの解説を読んで下さい、納得です。

2

りんごさんも回答されているようにテーブル→クエリ→フォーム→レポートがベストだと思います。
DSumは重くなります。

りんごさんが提示したリンク先
■T'sWare Access Labo #28 ~明細データテーブルの集計を考える~
には、

DSum関数を使った集計は、他のクエリーに比べて処理時間が極端に少なく、特にレコード移動した場合の優位性は歴然・・・・・・定義域集計関数は一般に遅いといわれるがなぜ?、理屈はサブクエリーと同じだと思うのだが

というような解説がありますが、これはテスト方法が間違っている。あるいはテスト結果の解釈が間違っていると思います。
テスト法は、DAOでレコードセットを開く、最終レコードへ移動する、ということだけをしています。
実際に使用する場合、集計結果を利用するはずです。集計結果を取得せずに最終レコード移動だけするという無意味な処理で速度を比較しても無意味だと思います。

具体的には下記のような処理にかかる時間を計測しています。

    Set qdf = dbs.QueryDefs(strQryName)
    Set rst = qdf.OpenRecordset() 'レコードセットを開く
    rst.MoveLast '最終レコードへ移動
    rst.Close
    qdf.Close

これでは上記で説明したように無意味なテストです。
下記のように各レコードにアクセスして集計結果を取得する処理を計測すべきでしょう。

    Set qdf = dbs.QueryDefs(strQryName)
    Set rst = qdf.OpenRecordset() 'レコードセットを開く
    Do until rst.EOF    
        Debug.Print rst!発注数 & "," & rst!入庫数 & "," & rst!出庫数
        rst.MoveNext
    Next
    rst.Close
    qdf.Close

これだとDSumが一番遅くなるはずです。レポートに出力する場合も、集計結果を出力することになるのでDSumが一番遅くなるはずです。

また、上記リンク先には下記のような解説もあります。

DSum関数を使ったクエリー「DSum集計」をデータシートビューで開くと、他のクエリーに比べて非常に画面表示に時間がかかる(1行ずつダラダラと表示されていく)のに、VBAのレコードセットとして扱うとかなり速い

実際にクエリを開くと時間がかかるといっています。
レコードセットとして扱うと速いといってますが、OpenRecordset と MoveLast だけでは速いのは間違いではないですが、実際問題、OpenRecordset と MoveLast だけの処理というのはありえません。

T'sWareさんのサイトは有用な情報が多いのですが、たまにこのように外してい情報があるので注意が必要だと思います。

私の経験上、下記のような動作だと推測しています。

集計クエリでは、OpenRecordsetした時点で集計をしている。
サブクエリを利用した集計では、OpenRecordsetした時点では集計はしていない。レコード移動するときに集計する。
DSumでは、OpenRecordsetした時点では集計しない、レコード移動しただけも集計しない、集計結果にアクセスするときにはじめて集計する。

DSumでの「他のクエリーに比べて非常に画面表示に時間がかかる(1行ずつダラダラと表示されていく) 」という動作からもそう推測できます。表示するとき(集計結果にアクセスするとき)にはじめて集計されるということだと思います。

1
りんご 2021/05/16 (日) 19:32:45 48103@0e907

テーブル→クエリ→フォーム→レポートでいいと思う。
Dsum動作比較は、下記、サイトがありました。

■T'sWare Access Labo #28 〜明細データテーブルの集計を考える〜
tsware

15
りんご 2021/05/16 (日) 19:12:35 48103@0e907 >> 14

ググっていたら、時間の計算に使えるかもしれないサイトがありました。

■T'sWare Access Tips #061 〜カレントレコードまでの累計を取得するクエリー〜
tsware

私の方からは、これくらいですね。頑張って👍

7
りんご 2021/05/16 (日) 18:53:19 48103@0e907 >> 5

 他の人は、旧バージョンを開いているとか?
 とりあえず「●●●件のレコードが更新されます」を試しに実行して、テーブルの中身を確認しましょう。全件削除実行からの一連の流れなので、何か問題が起きれば、手動全件削除で元に戻せますよね。
 前回のデータが残っているなら、全件削除のコードを比較。ループデータが残っているなら、For 〜Nextの中で、datasやrs(j)をdebug.printを比較。
 確認メッセージが出る出ないは、DoCmd.SetWarningsのコードがどこかにありませんか?
 確認した結果を教えてくれると、嬉しいな。

14
もんぞう 2021/05/16 (日) 18:35:24 62ea7@f778d

りんごさんへ

式の詳細ありがとうございす。
明日試してみます。

現在使ってるのが下の画像のようなものを使っております。
画像1

テーブル(外部データリンク)→クエリ→フォーム(サブフォームも)という流れでリアルタイムで更新できる仕組みを作ってます。
作業終了時間というフィールドを新たに追加したく今回質問させていただきました。
ただ作業生産性という少し専門的な分野の計算式が必要になってきますのでアクセスの質問掲示板を利用してもいいのか?という疑問は今もあります。
生産性と時間帯の人数(シフト)は基本的に固定で決まってますので、その部分は入力する予定です。
極端な話ですが一か月分入力することも可能です。
シフトのイレギュラーさえなければ一か月に一回のメンテでできればと考えております。
私のイメージとしてはクエリの部分で計算式を入れて作業終了時間を出せればと考えております。
そんな式が存在するのか?処理はできるのか?疑問は多々あります。
私の知識、技術不足のせいでうまく伝わっていないのかもしれませんので再度理想の形を説明させていただきました。

Excelで作るのが正解ではないでしょうか?
具体的にはわかりませんがExcelも必要であれば使うのは問題ありません。
更新すれば自動で作業終了時間がでる仕組みであれば他のこだわりは一切ありません。

いろいろと考えていただきありがとうございます。

13
りんご 2021/05/16 (日) 17:34:20 48103@0e907

 「フォームを使わない、テーブルとクエリだけで作る。」という方針であれば、新たに未完了のテーブルと持ち時間のテーブルを追加する必要はないです。

 新たにテーブルを作ります。追加するフィールドは、店舗名,チーム名,未完了,持ち時間、そして、下記の計算フィールドです。
・最大出荷数:[生産性]×[人数]×持ち時間
・出荷数:IIf([最大出荷数]>[未完了],[未完了],[最大出荷数])
・出荷時間:[出荷数]÷([生産性]×[人数])
・未完了残り:[未完了]-[出荷数]
・持ち時間残り:[持ち時間]-[出荷時間]

 計算フィールドの結果に応じて、店舗名、チーム名、未完了、持ち時間を自分で探して入力します。フォームを作ると、探す手間が少しだけ楽になるでしょう。テーブルとクエリだけで作るならば、たぶん、Excelで作るのが正解ではないでしょうか?
 クエリを頑張れば、ある程度、自動化出来るけれど、完成出来ずに重くなっただけ、なんてことも。

6
どんぐりず 2021/05/15 (土) 21:37:31 9099b@6e6cd >> 5

ありがとうございます。
コードを見直すということですが、1つ気になっているのが、自分の環境だと全くエラーが出ないのに、他の環境だとエラーが出ることです。
他の部分でも同じようなことが起こらないかと危惧しています。
これはどういった原因が考えられるでしょうか?

12
もんぞう 2021/05/15 (土) 19:21:58 62ea7@f778d

りんごへ

フォームに関してよく分かってない部分があり、テーブルとクエリで作成する感じでもよろしいでしょうか?
理解しにくい部分があるのですいません。

私の情報を整理します。
まず外部データのリンクのテーブルがあります。
とりあえずテーブルAにします。
[取引先CD] [取引先名]
[予定] [未完了]
[進捗]
上記のフィールドをテーブルAからクエリで抽出してます。
とりあえずクエリAにします。
どう言えばいいのかわかりませんが常に最新の情報に更新されます(手動)。

前回クエリAに追加したのが下記です。
現在時刻: Time()
残り時間: (([未完了]/([生産性]10))60)/1440
終了時間: [現在時刻]+[残り時間] [生産性]:テーブルを新たに作って追加しました。

ここまでが前回までです。

新たに未完了テーブルと持ち時間テーブルを追加する感じでよろしいでしょうか?
まったく見当違いのことを言ってたらすいません。

未完了テーブルの取引先名と未完了はクエリAにあるのですが必要でしょうか?

追加するフィールドについてですが、
チーム名:持ち時間テーブル
持ち時間:持ち時間テーブル
最大出荷数
出荷数
出荷時間
未完了残り
持ち時間残り

最大出荷数、出荷数、出荷時間、未完了残り、持ち時間残りの式を教えてもらえたら助かります。

終了時間に関してはまた別の機会に質問します。

大量に書き込んでいただいたのに方向性を変えて申し訳ありません。

5
りんご 2021/05/15 (土) 18:04:02 48103@0e907 >> 3

 AddDataのコードには、レコードを追加したら、(追加を確定する為に)更新すると書いてあるので、
確認メッセージ「●件のレコードが更新されます」が出るのは、正常に見えます。
 2件のレコードを編集する流れで、●●●件、つまり、3桁のレコードを変更する確認メッセージが出るならば、異常と考えて、例えば、For〜Next処理をdebug.printしてみるか、上記以外のコードを見直す感じでしょうか。

4
どんぐりず 2021/05/15 (土) 17:08:36 9099b@6e6cd >> 3

ごめんなさい、質問の内容が理解できなかったため、本文を少し具体的に修正しました。

3
りんご 2021/05/15 (土) 15:41:33 48103@0e907

 試していないので、あれですけど、例えば、
AddNew「10件のレコードを追加します。」
On Error Resume Next「1件」
Update「9件のレコードが更新されます」
という現象でしょうか?
 それとも、
AddNew「10件のレコードを追加します。」
On Error Resume Next「1件」
Update「100件のレコードが更新されます」
という現象でしょうか?

2
どんぐりず 2021/05/15 (土) 14:05:33 9099b@6e6cd >> 1

失礼しました。おっしゃるとおり、以前ここで教えていただいたAddDataのコードがあります。本文に追記しました!

1
りんご 2021/05/15 (土) 13:56:44 48103@0e907

もしかして、AddDataのコードが、上記の他にありませんか?
例えば、
【うどん屋プロシージャの呼び出し】
Call うどん屋("きつねうどん", "400円")
【うどん屋プロシージャの記述】
……

17

エラーメッセージの通りだと思います
画像1

新しく追加したプロシージャはReport_Openなので開く時プロパティに[イベント プロシージャ]を設定してください
ArrayListSort関数も省略しているので適当な場所に入れておいてください(汎用的に使える関数なので標準モジュールに入れてしまってもいいと思います)


[イベント プロシージャ]は各イベントのプロパティのプルダウンから常に選べるようになっているプロパティですが、これを指定すると、それぞれで専用のプロシージャを呼び出しなさいという指定になります(レポートの開く時ならReport_Openとか)

[イベント プロシージャ]を選んで[...]をクリックすると、対応するプロシージャが自動で生成されますが、コードをコピペしても[イベント プロシージャ]は自動で設定はされないので、この部分は自分でやる必要があります。

16

今の問題点は「詳細_Formatで正確なページ数が取得できない」なので「取得後の目次データの取り扱いをどうするか」は問題の解決にならないです

一応いろいろ眺めていたら解決案は出てきました(公開する段階にないですが)


レポートの最後に索引を追加したいということですよね。

一つのレポートで出力する。
索引は複数ページにわたる可能性がある。
索引は段組みレイアウトにしたい。
ということだと、かなり難易度が高いと思います。

これ自体は>> 7で出来てます。いろいろ議論の余地もあるかと思いますが、現時点で索引表示のためにワークテーブルを使う必要性は感じないです

11
りんご 2021/05/14 (金) 18:33:33 48103@0e907 >> 10

以下、フォームのイメージです。
①開始時間を入力する。店舗を選ぶ。
・出荷時間のリストボックス
店舗A,30
店舗B,90
店舗C,…
・開始時間のテキストボックス:9:00
・終了時間のテキストボックス:
…,店舗名,開始時間,終了時間
1,

終了時間を計算する。
・出荷時間のリストボックス
店舗A,30
店舗B,90
店舗C,…
・開始時間のテキストボックス:9:00
・終了時間のテキストボックス:9:30
…,店舗名,開始時間,終了時間
1,

③店舗名、開始時間、終了時間を計算。
・出荷時間のリストボックス
店舗A,30
店舗B,90
店舗C,……
・開始時間のテキストボックス:9:00
・終了時間のテキストボックス:9:30
…,店舗名,開始時間,終了時間
1,店舗A,9:00,9:30

④開始時間のテキストボックスに終了時間を入力
・出荷時間のリストボックス
店舗A,30
店舗B,90
店舗C,……
・開始時間のテキストボックス:9:30
・終了時間のテキストボックス:9:30
…,店舗名,開始時間,終了時間
1,店舗A,9:00,9:30
2,

10
りんご 2021/05/14 (金) 18:31:39 48103@0e907

終了時間は、開始時間に出荷時間を加える計算を考えてみました。
開始時間=9:00、終了時間=
開始時間=9:00、終了時間=9:30
開始時間=9:30、終了時間=9:30
開始時間=9:30、終了時間=11:00
まずは、先程のフォームの連結クエリをもとに、出荷時間のクエリを作ります。
店舗名,チーム名,出荷時間
店舗A,チーム9時 ,30
店舗B,チーム9時 ,30
店舗B,チーム10時,60
店舗C,チーム11時,……
店舗の終了時間を計算するときは、店舗名でグループ化、出荷時間の合計を集計しましょう。

9
もんぞう 2021/05/14 (金) 17:41:14 62ea7@f778d

りんごさんへ

たくさんのアドバイスありがとうございます。
難しそうですが、明日以降に試してみたいと思います。

15

このスレッドの流れを細かく読んではいませんので、外しているかも知れませんが、
ちょっと思ったことを書いてみます。

レポートの最後に索引を追加したいということですよね。

  • 一つのレポートで出力する。
  • 索引は複数ページにわたる可能性がある。
  • 索引は段組みレイアウトにしたい。

ということだと、かなり難易度が高いと思います。

一つのレポートで索引も出力するというのはあきらめて、
まずは、索引なしの医薬品集レポートを出力する。
その後、索引を出力する。
というようにレポートを2つに分けたらどうでしょう。

索引用のテーブルを作成しておいて、それから索引レポートを作成しておきます。

医薬品集レポートを出力するときに、フォーマット時イベントで索引用テーブルに索引用データを出力していく。

こうすれば、並べ替えも、段組みもレポートの機能で簡単にできます。

処理の流れは下記のようなイメージです。

フォームにコマンドボタンを2つ配置。
「医薬品集レポート印刷」
「医薬品集索引印刷」

「医薬品集レポート印刷」ボタンのクリック
索引テーブル の全データを削除 → 医薬品集レポートの印刷

医薬品集レポートの詳細(またはグループヘッダー)のフォーマット時イベントで索引データを索引テーブルに追加。

上記印刷後、「医薬品集索引印刷」をクリックで索引レポートを印刷。

13
hatena 2021/05/14 (金) 13:07:43 修正

まず、Forループ内でカウンター変数を変更するのはご法度です。Step を使いましょう。

データ追加は、サブフォームのレコードセットに対してAddNewで追加するようにします。
Withでサブフォームのレコードセットを参照するようしてますのて、
Me.T_月額マスタのサブフォーム1.Formは不要です。

![契約番号サブ] 等の[]内はコントロール名ではなく、フィールド名にしてください。

テーブルのフィールド名が「契約番号サブ」ならいいですが、「契約番号」なら、
![契約番号]
です。

あと、最後に .Update が必要です。

'請求月数の分だけ、サブフォームにレコードを追加する
Dim i As Long, s As Long
With Me.T_月額マスタのサブフォーム1.Form.Recordset
  '「ごとに請求」のコンボボックスで、以下の値が選択されている場合
  If Me.入金月頻度 = "2ヶ月" Then
      s = 2
  ElseIf Me.入金月頻度 = "半年" Then
      s = 6
  ElseIf Me.入金月頻度 = "1年" Then
      s = 12
  End If

  For i = 0 To 月数 Step s
      .AddNew
      ![契約番号] = Me.txt契約番号
      ![月額] = Me.月額
      ![入金月] = DateAdd("m", i, 開始年月)
      ![税率] = Me.税率
      ![税の処理] = Me.税の処理
      .Update
  Next
End With

リンクフィールドの設定は問題ないと思います。

12
だいふくもち 2021/05/14 (金) 10:44:14

リンク親フィールド/子フィールドが設定されている箇所が分かりましたので、念のため追記いたします。
画像1

14
norinori 2021/05/14 (金) 08:27:55

hirotonさん、本当に有難うござます。自分がやろうとしていたことが、素人には絶対無理だったと痛感しました。ご指導頂いた資料で今後じっくり勉強することにして・・・ とりあえず、このままコピペしてみました。添付しましたファイルの様なコメントが出ました。完全なコピペはダメだったでしょうか?画像1

8
りんご 2021/05/14 (金) 04:21:22 48103@0e907 >> 4

⑦リストボックスから、とりあえず泥臭く選んで登録する
未完了テーブルのリストボックス
1,店舗A,500
2,店舗B,1000
3,店舗A,0
持ち時間テーブルのリストボックス
1,チーム9時 ,60
2,チーム10時,60
3,チーム11時,60
4,チーム9時 ,30

…,店舗名,チーム名,未完了,持ち時間,最大出荷数,出荷数,出荷時間,未完了残り,持ち時間残り
1,店舗A,チーム9時 ,500 ,60,最大出荷数,500,30,0,30
2,店舗B,チーム9時 ,1000,30,

7
りんご 2021/05/14 (金) 04:02:54 48103@0e907 >> 4

店舗A,未完了残り0を登録
未完了テーブルのリストボックス
1,店舗A,500
2,店舗B,1000
3,店舗A,0
チーム9時,持ち時間残り30を登録。
持ち時間テーブルのリストボックス
1,チーム9時 ,60
2,チーム10時,60
3,チーム11時,60
4.チーム9時 ,30
出荷時間のログ
…,店舗名,チーム名,未完了,持ち時間,最大出荷数,出荷数,出荷時間,未完了残り,持ち時間残り
1,店舗A,チーム9時 ,500 ,60,最大出荷数,500,30,0,30

6
りんご 2021/05/14 (金) 03:43:15 48103@0e907 >> 4

 未完了テーブルのリストボックス
 1,店舗A,500
 2,店舗B,1000
 持ち時間テーブルのリストボックス
 1,チーム9時 ,60
 2,チーム10時,60
 3,チーム11時,60
  ④リストボックスから、店舗A、チーム9時、未完了500、持ち時間60を選んで登録。
 以下、フォームの連結クエリのイメージです。
 …,店舗名,チーム名,未完了,持ち時間,最大出荷数,出荷数,出荷時間,未完了残り,持ち時間残り
 1,店舗A,チーム9時 ,500 ,60,以降、計算で導出。

5
りんご 2021/05/14 (金) 03:20:47 48103@0e907 >> 4

 未完了のログと持ち時間のログを考えてみました。持ち時間は、9:00~10:00ならば、60とします。
以下、フォームのイメージです。
 ① 出荷日を選ぶ。
 ② 店舗名を選んで登録。
未完了テーブルのリストボックス
1,店舗A,500
2,店舗B,1000
   ③ チームを選んで登録。
持ち時間テーブルのリストボックス
1,チーム9時 ,60
2,チーム10時,60
3,チーム11時,60

11
だいふくもち 2021/05/13 (木) 17:25:30

情報が足りずに申し訳ありません…

  • 「ごとに請求」ボタンに埋め込んでいるマクロのコード
    '請求月数の分だけ、サブフォームにレコードを追加する
    Dim i As Long
    With Me.T_月額マスタのサブフォーム1.Form.Recordset
      For i = 0 To 月数
          .AddNew
          Me.T_月額マスタのサブフォーム1.Form![契約番号サブ] = Me.txt契約番号
          Me.T_月額マスタのサブフォーム1.Form![月額サブ] = Me.月額
          Me.T_月額マスタのサブフォーム1.Form![入金月サブ] = DateAdd("m", i, 開始年月)
          Me.T_月額マスタのサブフォーム1.Form![税率サブ] = Me.税率
          Me.T_月額マスタのサブフォーム1.Form![税の処理サブ] = Me.税の処理
          '「ごとに請求」のコンボボックスで、以下の値が選択されている場合
          If Me.入金月頻度 = "2ヶ月" Then
              i = i + 1
          ElseIf Me.入金月頻度 = "半年" Then
              i = i + 5
          ElseIf Me.入金月頻度 = "1年" Then
              i = i + 11
          End If
      Next
    End With
    
  • サブフォームのリンク
    親フィールド:「T_契約マスタ」の「契約番号」
    子フィールド:「T_月額マスタ」の「契約番号」
    (リレーションシップで結ばれている関係をリンクフィールドと解釈しているのですか、相違ありませんでしょうか…?)
    画像1

  • サブフォーム上で手入力した場合は問題なく入力できました。

以上、どうぞよろしくお願いいたします。

13
hiroton 2021/05/13 (木) 14:46:46 修正 d3c7a@f966d

というわけで、ちゃんと使いやすいデータにして対応する例
Dictionary オブジェクトを使って目次データを整理するようにします

Option Compare Database
Option Explicit

Dim dicIndex As Object

Private Sub Report_Open(Cancel As Integer)
    Set dicIndex = CreateObject("Scripting.Dictionary")
End Sub

Private Sub 詳細_Format(Cancel As Integer, FormatCount As Integer)
    Dim indexString As String
    indexString = Left(Me!薬品名 & String(12, "・"), 12) & Format(Me.Page, "@@@")

    With dicIndex
        If .Exists(Me!薬品名のフリガナ.Value) Then
            .Item(Me!薬品名のフリガナ.Value) = indexString
        Else
            .Add Me!薬品名のフリガナ.Value, indexString
        End If
    End With
End Sub

Private Sub レポートフッター_Format(Cancel As Integer, FormatCount As Integer)
    Static isExecuted As Boolean
    Dim arr
    Dim s
    Const colCount = 3  '1ページの段数
    Const rowCount = 30 '1ページの行数
    Dim CNT As Long
    Dim colName As String

    If Not isExecuted Then
    
        '並び替え用配列の準備
        arr = dicIndex.Keys
        '並び替え用配列を出力順に並び替え
        Call ArrayListSort(arr)
    
        '出力順にデータを取り出して段組みに振り分ける
        CNT = 0
        For Each s In arr
            colName = "txt目次" & CNT \ rowCount Mod colCount
            Me(colName) = Me(colName) & dicIndex.Item(s) & vbCrLf
            CNT = CNT + 1
        Next

        isExecuted = True
    End If
End Sub

Dictionary オブジェクトを使うには事前準備が必要なのでレポートの開く時イベントに処理を追加しています。

Dictionary オブジェクトの仕様上「薬品名のフリガナ」に重複データがあると最後の「薬品名」のみ目次に反映されます

12
hiroton 2021/05/13 (木) 14:04:00 d3c7a@f966d

五十音での並び替えについて

とりあえず無理やり的な方法で(修正箇所だけ)

'詳細_Format内
    keepIndexString = Me!薬品名のフリガナ & "<split>" & Left(Me!薬品名 & String(12, "・"), 12) & Format(Me.Page, "@@@") & vbCrLf

'レポートフッター_Format内
            Me(colName) = Me(colName) & Mid(s, InStr(s, "<split>") + 7) & vbCrLf

例えば

名称かな
茨城県いばらき
栃木県とちぎ
群馬県ぐんま
埼玉県さいたま
千葉県ちば
東京都とうきょう
神奈川県かながわ

のようなデータがあった場合、

出力データ
いばらき<split>茨城県
とちぎ<split>栃木県
ぐんま<split>群馬県
さいたま<split>埼玉県
ちば<split>千葉県
とうきょう<split>東京都
かながわ<split>神奈川県

のようにひとかたまりの文字列のデータにして並び替えた後、分割用の文字から後ろを抜き出せば「かな順」で並び替えができるというものです
「<split>」は誤動作しないよう「かな」に含まれない文字列なら何でも構いません


内容が複雑化してきて、簡素化した記述が足かせになって余計な苦労をしてるような気がしてきました。データのボリュームが増えてきているのでコード内でもしっかりデータを管理できるような仕組みを導入したほうがよさそうです

11
hiroton 2021/05/13 (木) 11:48:32 d3c7a@f966d

適当なデータを作って試してみたら確かにうまくいかないですね
レポートのイベントの発生メカニズムの研究(hatena chipsさん)

画像1

ページ跨ぎが発生した場合に目次データが重複しないよう

    If FormatCount = 1 Then

と制御を入れたんですが、FormatCount = 1だけだとうまく目的のデータにならないようです。画像を見てわかる通り、目次データの取得は「実際の描画があったら目次データを作成する(ページ番号を取得する)」とする必要がありそうです。hirotonはうまい方法を知りません

目次データを取得している詳細_Formatイベントは描画前の処理なので、このタイミングで「描画があったかどうか?」は知りようがありません。やるとすれば、印刷しようとしている余白に印刷できる高さがあるかどうかを計算するという方法になると思います。現在の印刷位置情報や、印刷領域の残り高さが必要になるのでかなり大変です


条件を限定すれば、いくらか簡単な方法でチェックすることもできそうです

同一ページ印刷プロパティ「はい」
単独で1ページを超えるような出力がない(上図の例なら詳細は最大でも9行(1ページで収まる)場合)

であれば、「FormatCount = 2があれば、それが描画ページ」とすることができます。ただ、FormatCount = 1のときはFormatCount = 2があるかどうかわからないので、「仮データを置いて、次の明細に移動したら仮データの確定処理をする」様にします

Option Compare Database
Option Explicit

Dim indexText As String
Dim keepIndexString As String

Private Sub 詳細_Format(Cancel As Integer, FormatCount As Integer)
    Static preItemName As String
    
    '仮データの確定処理
    If preItemName <> Me!薬品名 Then
        indexText = indexText & keepIndexString
        preItemName = Me!薬品名
    End If
    
    '仮データを作成
    keepIndexString = Left(Me!薬品名 & String(12, "・"), 12) & Format(Me.Page, "@@@") & vbCrLf

End Sub

Private Sub レポートフッター_Format(Cancel As Integer, FormatCount As Integer)
    Static isExecuted As Boolean
    Dim arr
    Dim s
    Const colCount = 3  '1ページの段数
    Const rowCount = 30 '1ページの行数
    Dim CNT As Long
    Dim colName As String

    If Not isExecuted Then
        '最後の明細の仮データの確定処理
        indexText = indexText & keepIndexString
    
        '並び替えのために配列にする
        arr = Split(indexText, vbCrLf)
        '配列を並び替え
        Call ArrayListSort(arr)
    
        '段組みに振り分ける
        CNT = 0
        For Each s In arr
            colName = "txt目次" & CNT \ rowCount Mod colCount
            Me(colName) = Me(colName) & s & vbCrLf
            CNT = CNT + 1
        Next

        isExecuted = True
    End If
End Sub

'ArrayListSort関数は省略
10

下記の情報を提示してもらえますか。

「ごとに請求」ボタンのクリック時イベントのVBAコード。
サブフォームコントロールの「リンク親フィールド」「リンク子フィールド」の設定。
サブフォームで手入力で入力したときは問題なく入力できるかどうか。