Option Compare Database
Option Explicit
Const L = 567 * 4 'グラフの左位置 5cm
Const Rng = 567 * 0.06 '1日の幅 0.06cm
Dim FDate As Date
Private Sub Report_Load()
FDate = DateSerial(Me.txt年, 1, 1)
End Sub
Private Sub ページヘッダーセクション_Print(Cancel As Integer, PrintCount As Integer)
'月ラベル
Dim m As Long, d As Long
For m = 1 To 12
d = DateDiff("d", FDate, DateSerial(Me.txt年, m, 1))
Me.CurrentY = Me.txt年.Top
Me.CurrentX = L + d * Rng
Me.Print m & "月"
Next
End Sub
Private Sub 詳細_Print(Cancel As Integer, PrintCount As Integer)
Me.DrawStyle = 0
Me.ForeColor = RGB(150, 150, 150)
'罫線
Dim m As Long, d As Long
For m = 1 To 13
d = DateDiff("d", FDate, DateSerial(Me.txt年, m, 1))
Me.Line (L + d * Rng, 0)-(L + d * Rng, 1000)
Next
Me.DrawWidth = 1
Me.DrawStyle = 6
Me.FillColor = RGB(90, 150, 200)
Me.FillStyle = 0
Me.Line (L + DateDiff("d", FDate, Me.開始日) * Rng, 50)-(L + DateDiff("d", FDate, Me.終了日) * Rng, 330), 0, B
End Sub
Private Sub ボタン_Click()
If Me.NewRecord Then
CurrentDb.QueryDefs("追加クエリ").Execute
me.Requery
Else
CurrentDb.QueryDefs("更新クエリ").Execute
me.Refresh
End If
End Sub
回答の前に
画像は下記のアップロードボタンでアップロードするとページ内に表示できますので、それを利用してください。
詳細は下記を参照してください。
Microsoft Access 掲示板 の使い方 Microsoft Access 掲示板 - zawazawa
下記のように表示できます。
回答
最初の画像のようにするなら、
メインフォームは非連結にする。
T_顧客マスタから連結フォームを作成。
T_月額マスタとT_契約マスタを結合させてクエリから連結フォームを作成。
この2つのフォームをサブフォームとして埋め込むという設計にするといいと思います。
メインフォームの「すべて入力」ボタンで指定した期間のデータをVBAで追加するとようにします。
VBAは必要になりますが、すべて非連結でするより、設計もシンプルだしコード量もはるかに少なくなります。
ただ、Accessのフォームに扱いに慣れている必要があります。
Accessの初心者なら、まずは入門書か入門サイトで基本のフォーム設計を習得しておくといいでしょう。
>hatena様
ご回答いただきありがとうございます!また、URLも教えていただきありがとうございます。
確かにクエリを間に挟まずに、直接テーブルに繋げた方が無駄がなさそうです…
色々と調べてみたのですが、連結フォームを用いた登録方法は
下記の画像のようなフォームで、一件ずつレコードを登録していくやり方が主流のようでした。
hatena様が想定されているのは以下のようなフォームで合っておりますでしょうか…?
ご回答いただいた内容を上手く汲み取れず申し訳ありません…
非連結ではなく、メイン/サブフォーム形式の連結フォームでいいと思いますが、だめでしょうか。
Accessのフォームのメイン/サブフォームとは | できるネット
サブフォームを含むフォーム (一対多のフォーム) を作成する - Access
サンプルを作成してみました。
テーブル名は、T_プロジェクトに変更しました(T_登録では内容がわからないので)。
フォーム上にコンボボックスとコマンドボタンを配置して、コンボボックスで年を選択します。
コマンドボタンをクリックするとレポートのプレビューが開きます。
フォーム名 フォーム1
コンボボックス名 cbYear
コマンドボタンクリック時
レポート名 R_プロジェクト
レポートのレコードソース T_プロジェクト
ページ設定 用紙 A4 横
ページヘッダーにテキストボックスを配置する。
名前 txt年
コントロールソース =[Forms]![フォーム1]![cbYear]
レポートモジュール
下記をクリックするとサンプルファイルをダウンロードできます。RptGanttChart_Year.zip
返答ありがとうございます、早速本題に入らせて頂きます。
テーブル名:T_登録
フィールド名:登録日、開始日、終了日、プロジェクト名、状態
各プロジェクトを年間で管理し、完了している案件か、様子見で終わった案件なのかを一覧可能に出来たらと考えております
。
お忙しい中恐縮ではございますが、ご指導のほどよろしくお願い致します。
「1年間の日付管理」といっても具体的にどのようなレイアウトなのか分かりません。
エクセルとかでレイアウトをイメージを作成して、画像で提示してもらえませんか。
あと、もとになるテーブルのテーブル名、フィールド名、データ例も提示してください。
解決です。ありがとうございます。
本当に助かりました。
西暦の2桁問題は2000年問題だけだと思ってましたが
こんなところにも存在していたんですね。
業務で人名リストを作成していて1950年以前の方が
表示できなくて困ってました。
本当にありがとうございました。
windowsの設定の問題ですね
日付システム、日付形式、2 桁で表された西暦の解釈方法を変更する
windows10の場合デフォルトが1950年~のようです。この設定を変えれば表示は変わります
テーブルを支出と収入の2つに分けずに、最初から画像の現金出納帳の形の設計しておけばいいと思います。
ユニオンクエリは面倒ですし、更新できない、重い、などデメリットしかありません。
支出調書と収入調書は、現金出納帳テーブルから選択クエリで簡単に作成できます。
日計と累計は、クエリで作成しなくてもレポートでグループ化の機能と集計実行で簡単に表示できます。
面倒なクエリで表示させる必要性はないと思います。
外部アプリとの連携でエクスポートするときとか、特殊な用途のときに利用せざるを得ないときもありますが、そうでなければわさわざ面倒なクエリでする必然性はないです。
データベースとしての設計が正しくできていれば、データ数が増えてもそれほど重くなることはないです。
具体的には「テーブルの正規化」、「適切なインデックス設定」です。
テーブル設計は「テーブルの正規化」についてしっかり理解してから始めたほうがいいと思います。
データが増えてから、正規化しようとすると面倒ですので。
WEB検索すれば解説ページが多数見つかります。例えば、
正規化とは - もう一度学ぶMS-Access
心配なら、ダミーのレコードをVBA等で作成して、検証することも可能です。
「ダミーデータ生成」とか「テストデータ生成」をキーワードにWEB検索すればWEBツールが見つかりますので、それを利用してもいいでしょう。
まずはテーブルの正規化ができたなら、入力し始めていいと思います。重くなってから分割を検討しても遅くないと思います。分割自体はそれほど面倒なことではないので。
1000件程度なら、DCount()やDSum() でもそれほど重くならないように思います。もし、それで遅くなるようなら、リンク先の関数を利用するの方法に変更すればいいでしょう。
リンク先の方法も関数コードをコピーして標準モジュールに張り付けて、あとは簡単なコードを1行記述するだけで使えます。
hatena様
いつもお世話になっております。
ご教示して頂きありがとうございます。
土・日曜日の日数は、年の最初の日付の曜日の取得と計算はどのように求めたらいいでしょうか。
お忙しいと思いますがよろしくお願いします。
祝日は格納テーブル作成して、DCount関数でカウントしてみようと思っています。ありがとうございます。
EXCELのCOUNTSUMも、どうようにすべてを対象として計算されるので動作的には同じようなものでしょうか?
一年に数人分で1000件程度になるかと思います
一年間に絞って計算させる、といったようなことをすれば軽くなるでしょうか?
リンクを読みましたが、経験が浅くあまり理解できませんでした
累計は特に重くなります。すべてのレコードで過去にさかのぼって集計することになりますので。
その場合は、テーブルに累計値を格納するフィールドを持たせて、VBAで計算して累計値を書き込むような設計にする場合もあります。
下記で、簡単に累計値をテーブルに書き込める汎用関数を紹介していますので、ご参考に。
累計値をテーブルに自動入力する関数 - hatena chips
逆ですね。クエリを元にSQLを書く時、後からフィールドは追加できません。
先に汎用クエリにそれぞれのレポートで必要なフィールドをすべて表示させておきます。
フィールド名を一つずつ指定するのは面倒なので、テーブル名.* と設定しておけば、テーブルのすべてのフィールドが表示されます。
レポートでレコードソースで必要に応じてフィールドを選択したり、演算フィールドを追加したりします。
例えば日付フィールドだけを置いたクエリを作っておき、ほぼすべてのレポートでそれを使う
別途SQLをかき、そのレポートに必要なフィールドを追加するということですか?
ソースのところに[フィールド名]でどんどん書き込むのでしょうか?
再計算のたびに毎回全レコード対象で計算がはいるので激重になりそうですね
労働時間の管理なんかには向かないのですかね
せめてその日、までの累計を計算したいです
出勤や退勤に変化があったときに計算して累計に格納するようにVBAを書いても
レコードが増えると重いですねえ
ACCESSにはDCount()やDSum()のような定義域集計関数と呼ばれる関数があります。これらを使えば「COUNTIFSやCOUNTSUM」と同様の計算ができます
ただし、計算速度的に低速なため、多用すると処理速度の問題で不可となる場合があります
この「処理速度的に不可」は環境依存度が高いのでやってみなければわかりません。ダメだったときは高速な手法を考えることになるので大変だと思います
使いまわし早めて、それぞれ別のサブフォームとして独立させることとします。
ありがとうございました
はい、それでいいです。
状況次第ですので、なんとも言えません。
それぞれレポートの表示するフィールドの違いとか、クエリの複雑さとか、いろいろです。
私の場合は下記のような設計する場合が多いです。
複数のレポートで使用できるように汎用的なクエリを一つ作成しておく。
各レポートのレコードソースに汎用クエリを使ったSQLを設定する。SQLは直接記述してもいいし、ビルドボタンを押せば、クエリのデザインビューで編集できます。
これだと、クエリは最低限の数ですみますので管理が楽になります。クエリがあまり増えると管理が大変ですので、なるべく増やさない方向で設計します。
サブフォームのレコードソースのクエリ、または、コントロールソースで、フォームAを参照しているということでしょうか。
もし、使いわわしたいなら、この参照はやめて別の方法を考えることになるでしょう。
下記のようないくつかの方法が考えられます。状況に応じて選択してください。
メインフォームの「リンク親フィールド」「リンク子フィールド」の設定でフィルタリングする。
親フォームのVBAでFilterプロパティを設定してフィルタリングする。
サブフォームからの参照を絶対参照ではなく相対参照にする。(メインフォームが変わっても条件が同じになる場合)
[Parent]![コントロール名] で親フォームのコントロールを相対的に参照できます。
なかなかむずかしそうですね
EXCELでやっていたときは
COUNTIFSやCOUNTSUMをつかってやっていました
・月の所定労働時間から実際の勤務時間を引いていき、当月あと何時間勤務できるかを表示
というのもなかなか大変そうですか?
ご回答ありがとうございます
このサブフォームは2つのメインフォームで使用する汎用フォームとして設定しましたが、
今回問題にしているメインフォーム(フォームA)でフィルタリングがあるため、
別のメインフォーム(フォームB)を開くときに、フォームAのテキストボックスに関する
パラメータ入力ダイアログを要求されて困っています。
そのため、合計はサブフォームではなくメインフォームで計算しようと考えました。
(できない理由は理解しました)
サブフォームの使いまわしをやめるしかないでしょうか?
Sum関数は、自身のフォームのレコードソースのフィールドを対象とします。別フォームのフィールドは使用できません。サブフォームでも同様です。
サブフォーム内の =Sum([Qty]) のテキストボックスを参照するようにしてください。このテキストボックス名を SumQty として、メインフォームのテキストボックスのコントロールソースを下記のように設定します。
サブフォーム内の =Sum([Qty]) を表示させたくない場合、可視を「いいえ」にしておけばいいでしょう。
そのフォームでしか使わず、かつ、特定の日付を元に計算するなら計算式一つでやってもいいんじゃないかな
週ごとの集計を表示したいとか、年間の集計を表示したいとかになると処理の効率化も考えたほうがよさそうだけども
週を識別するIDを作りたいだけなら
Int([日付]/7)
で計算させてもいいんじゃないですかね簡単なのは定義域集計関数を使ってQ1上で計算する方法かな?
DSum 関数
ex)
アドバイスありがとうございます。
試してみます
恥ずかしながら、queryについてよく把握できていません。
調べてみます。
集計クエリ、また、集計クエリを含むクエリは更新できません。
入力できる状態で合計を表示したい場合は、DSum関数、DCount関数などで集計すれば可能です。ただし、件数が多いと重くなりがちです。
合計:フィールド1 + フィールド2
というのはカレントレコード内のみでの計算ですのですぐに反映されます。100以上:DCount("合計","クエリ1","合計>100")
というのは複数レコードを対象とする集計ですので反映させるには、閉じてから開くか、レコード保存した上で再クエリする必要があります。アドバイスありがとうございます。
試してみます
前もって作成しておいてもいいでしょう。手入力が面倒なら、VBAか追加クエリで一気に生成することもできます。
あるいは、フォームで新規入力するときに、VBAで自動入力してもいいでしょう。
土・日曜日の日数は、年の最初の日付の曜日が取得できれば、計算で求められますね。
祝日は祝日を格納するテーブルを作成しておいて、DCount関数でカウントすればいいでしょう。
あるいは、祝日判定関数を利用してカウントしてもいいでしょう。例えば下記で公開されている関数が使えます。
AddinBox(祝日マクロ-1)
サブフォームのレコードの内容を変更する
かつ
M_鍵マスターの情報はメインフォームにもサブフォームにもない
なので、クエリで修正すればいいですね。ただし、サブフォームのレコードの状態が新規レコードの場合と既存レコードの場合の2通りが考えられるので、状態をチェックして追加クエリか更新クエリか、どちらを実行するか条件分岐が必要でしょう
集計フィールドで使える関数には制限があります。
「その数値にランダムで5~10を加算した数値」はどのように取得しているのですか。
Rnd関数を使っているのなら、集計フィールドでは使えません。
他にもDate関数とかNow関数のようにその時々で異なる値を返す関数は使用不可です。
「ランダムな数値」ということはその時々で異なる値を返すことになるので集計フィールドでは無理だと思います。
ちょっと調べてみたのですが、集計フィールドというので、フォームAにランダムで加算する、とういうのは運用的にはだめなのでしょうか?
テーブル名 T_週のレコードは前もって数年分つくるもいうことですか?
「週ID」フィールドも勤務時間管理テーブルに持たせます
といのは、どのように入力するのですか?
初心者で理解力がなくてすみません
hatena様
いつもお世話になっております。
早速のご返答ありがとうございます。
該当一年間で土・日曜日の日数や祝日日数をレポートに表示させる為にはどうすればいいでしょうか。
よろしくお願いします。
早速のご返事、誠にありがとうございます。
参考にさせていただきます。
テーブル イベントにデータ マクロを追加する
比較的新しい機能で、テーブルに直接機能を追加することはできますね。hirotonは使ったことありません。情報の少ない仕組みはそれだけで生産性が落ちるので
フォームを介しての実装はテンプレみたいなものなのでしょう。目的自体は単純なモノのように見えるので「フィールドA→フィールドB」で実装できているものがあるなら「不具合」はないと思いますよ