Private Sub btnInput_Click()
On Error GoTo ErrHandler
If Nz(Me.cmbP_Name, "") = "" Or Nz(Me.txtQty, "") = "" Then
MsgBox "Fill P_Name and transaction Quantitiy", vbExclamation, "Caution"
Exit Sub
End If
Dim sngQty As Single
If Nz(Me.opgTzT, "") = "" Then
MsgBox "Choice transaction type", vbExclamation, "Caution"
Exit Sub
ElseIf Me.opgTzT = 21 Or 22 Then
sngQty = Me.txtQty
Else
sngQty = Me.txtQty * -1
End If
' フォームのレコードセットに直接データ入力
With Forms!F_Display!sbf_Display.Form.RecordsetClone
.AddNew
!T_Time = Me.txtTzDate.Value
!P_ID = Me.cmbPName.Column(0)
!TID = Me.opgTzT
!Qty = sngQty
!Memo = Me.txtMemo
.Update
End With
db.Execute strSQL
MsgBox "Already Inputed"
Call initilizeForm
Exit Sub
ErrHandler:
MsgBox "Error #: " & Err.Number & vbNewLine & vbNewLine & _
Err.Description, vbCritical, "Error"
End Sub
Private Sub btnInput_Click()
On Error GoTo ErrHandler
If Nz(Me.cmbP_Name, "") = "" Or Nz(Me.txtQty, "") = "" Then
MsgBox "Fill P_Name and transaction Quantitiy", vbExclamation, "Caution"
Exit Sub
End If
Dim sngQty As Single
Dim strSQL As String
If Nz(Me.opgTzT, "") = "" Then
MsgBox "Choice transaction type", vbExclamation, "Caution"
Exit Sub
ElseIf Me.opgTzT = 21 Or 22 Then
sngQty = Me.txtQty
Else
sngQty = Me.txtQty * -1
End If
' SQLによる、データ入力
strSQL = _
"INSERT INTO T_SeihinTorihiki (T_Time, P_ID, TID, Qty, Memo) " &
"VALUES(" &
"#" & Me.txtTzDate & "#, " &
"'" & Me.cmbPName.Column(0) & "', " &
Me.opgTzT & ", " &
sngQty & ", " &
"'" & Me.txtMemo & "' );"
Dim db As DAO.Database
Set db = CurrentDb
Function f_strInsAfter(strOrg As String, strBgn As String, strEnd As String, strIns As String) As String
Dim p1 As Long
Dim p2 As Long
p1 = InStr(strOrg, strBgn)
If p1 = 0 Then
f_strInsAfter = strOrg
Exit Function
End If
p2 = InStr(p1, strOrg, strEnd)
If p2 = 0 Then
f_strInsAfter = strOrg
Exit Function
End If
If Len(strOrg) < (p2 + Len(strEnd)) Then
f_strInsAfter = Left(strOrg, p2 + Len(strEnd) - 1) & strIns
Else
f_strInsAfter = Left(strOrg, p2 + Len(strEnd) - 1) & strIns & f_strInsAfter(Mid(strOrg, p2 + Len(strEnd)), strBgn, strEnd, strIns)
End If
End Function
よくわかりません。
しかし、InputフォームのCall Initialize Formの後に
Forms!F_Display!sbf_Display.Requery
を挿入して更新させています。
VBAの Line メソッド で線を描画すると、DrawWidth プロパティで線の幅を1ポイント単位で設定できます。
Report. Line メソッド (Access) | Microsoft Docs
DrawWidth プロパティ (Access) | Microsoft Docs
Q_Dislay クエリを直接開いたときにそのクエリで更新できますか。
更新できないなら、更新できるような設計にする必要があります。
いままで
サブフォームsbf_DisplayのソースオブジェクトがF_Display_2(そのフォームのレコードソースがQ_Dislay)
となっていました。
(お伝えし忘れていました。すいません)
これを、
サブフォームsbf_DisplayのソースオブジェクトがQ_Display
にしたところ、エラーの発生が解消されました。
理由が全く分からないのですが、何が違うのでしょうか。
だめでした(変化ありません)
!T_Time = Me.txtTzDate.Value
のところで、Error3164 Field cannnot be updatedが出ました。
別案
下記の1行を追加するとどうでしょうか。
帳票フォームです
Docmd.OpenForm "PF_Input1",,,,,acDialog
Private Sub btnInput_Click()
On Error GoTo ErrHandler
If Nz(Me.cmbP_Name, "") = "" Or Nz(Me.txtQty, "") = "" Then
MsgBox "Fill P_Name and transaction Quantitiy", vbExclamation, "Caution"
Exit Sub
End If
Dim sngQty As Single
Dim strSQL As String
If Nz(Me.opgTzT, "") = "" Then
MsgBox "Choice transaction type", vbExclamation, "Caution"
Exit Sub
ElseIf Me.opgTzT = 21 Or 22 Then
sngQty = Me.txtQty
Else
sngQty = Me.txtQty * -1
End If
' SQLによる、データ入力
strSQL = _
"INSERT INTO T_SeihinTorihiki (T_Time, P_ID, TID, Qty, Memo) " &
"VALUES(" &
"#" & Me.txtTzDate & "#, " &
"'" & Me.cmbPName.Column(0) & "', " &
Me.opgTzT & ", " &
sngQty & ", " &
"'" & Me.txtMemo & "' );"
Dim db As DAO.Database
Set db = CurrentDb
db.Execute strSQL
MsgBox "Already Inputed"
Call initilizeForm
GoTo Finally
ErrHandler:
MsgBox "Error #: " & Err.Number & vbNewLine & vbNewLine & _
Err.Description, vbCritical, "Error"
Finally:
If Not db Is Nothing Then
db.Close
Set db = Nothing
End If
End Sub
以上です。
インプットフォームはほかにこれといったコードがありません。初期化のためのInitialize Formと、閉じるボタンくらいです。
書式プロパティはフィールドに対して一つしか設定できませんので、「単位」フィールドは必要ですね。
表計算ソフトのEXCELとデータベースソフトのAccessでは根本的に違いますので、Excelでの発想は捨てて取り掛かりましょ
う。
「単位」フィールドをテキスト型にしてユーザーに自由に入力させると、km ㎞ Km Km などと表記ぶれが発生します。これはデータベースにとっては致命的ですので、マスターの方に単位フィールドを持たせるようにします。
テーブル例
T商品マスター
商品コード 主キー
商品名
単価
単位
T受注
受注コード 主キー
受注日
商品コード
数量
クエリを作成して、上記の2つのテーブルを追加して、商品コード同士で結合します。
T受注 の全フィールドを表示させて、T_商品マスターからは、商品名、単価、単位 を表示させます。
このクエリからフォームウィザードで入力フォームを作成します。
このフォームで商品コードを入力すると、商品名、単価、単位 が自動で表示されます。
このような設計にすると、表記ぶれは発生しません。
どの単位かはフィールドごとに固有でつけます
距離をいれるフィールドにはkmといった具合です
単位フィールドは作っていませんがそのようにするものですか?
EXCELの書式のようなイメージで質問しました
どの単位にするかはどのように決定されるのですか。
「単位」のフィールドが別にあるなら、コントロールソースを下記のように設定すればいいでしょう。
=[数値フィールド] & [単位]
メイン/サブフォーム形式でサブフォームは帳票フォームかデータシートですよね。
だとしたら連結フォームにするしかないです。(非連結では1レコード分のデータしか表示できない。)
これも連結フォームになります。レコードソースをデザインビューで設定するかVBAで設定するか、だけの違いですので。
とりあえず一部分のコードだけでは、全体像が把握できませんので、
インプット用のフォームを呼び出すイベントプロシージャ全体。
インプット用のフォームのコード全体を提示してもらえますか。
ご回答ありがとうございます
テーブルと連結させる必要はありません。(簡単に表示させるために連結というスタイルをとりました)
sbf_Displayとテーブル(クエリ)の連結を取り、F_DisplayのLoadイベント時に
[Forms]![F_Display]![sbf_Display].Form.Recordsource = (SQL文)として表示させましたが、これも同じでした。
(この場合も連結になってしまうのでしょうか)
サブフォームに直接打ち込む方法でなく、インプットフォームを利用したいとする場合はどうするのでしょうか?
あ、次回の案件を作る際部分的にフィールドを引っ張る際に、既に冗長になりますね…
改めて考え直します…
そういうことだったんですね!おかげさまでうまくいきました。
F_Displayおよびsbf_Displayがテーブル(またはクエリ)と連結しているフォームなら、フォームでデータを入力するという考えかたにすべきです。
VBAで新規レコードに移動して、そこでフィールドに代入するか、
フォームのRecorsetプロパティでレコードセットを取得してそれに対してAddNewするのが王道です。
FollowHyperlink は本来はURLからWEBページを開くものなので、URLには使えない文字は受け付けないのだと推測。
URLで使用可能な文字、使用できない文字
フォルダーを開くなら、Shell関数でエクスプローラーを起動すればいいでしょう。
下記でどうてしょうか。
リッチテキスト形式を使ってみては?
リッチテキストフィールドを作成または削除する
リレーション組めれば楽なのにってパターンですね。あるあるです。が、データベース的にはあまり考えたくない特殊な条件なので質問時点で記載があるとよかったかなぁと思います
この条件だと、最後に提示したメイン-サブフォーム形式は使えないので「T_モニタリング(ケアプランID)」と「T_ケアプラン(プランID)」で(想定とは逆向きの)一対多でクエリを組んで計画日を拾うためだけの形で運用します
ケアプランIDは計算で求めることになる(求められる)のでフィールドに持つ必要はないともいえるのですが、結構複雑な処理になるので必要なタイミングで取得したらデータとして保存する(「ケアプランID」フィールドを設ける)というのがやはり扱いやすいと思います
質問では評価記入の基準のために「評価日」を設ければいいのではないか?としていますが、ケアプランIDがあればその計算は簡単なのと、ケアプラン側から評価の一覧を見たいとなった場合、ケアプランIDでモニタリングのデータが抽出できる等のメリットもあります
こうすると問題点が2つ上がってきます
1.どのタイミングでケアプランIDを取得するか、その求め方
求め方については、モニタリングの計画日がケアプランの計画期間内になるようなケアプランIDを拾えばいいので次のような式で求められます
「計画期間終」の入力が実際のプラン終了時(それまでは未入力)なんて場合は
Nz([計画期間終], DataAdd("m", 6, [計画日])-1)
等、手入れが必要になると思いますタイミングは、まず、モニタリングのデータ入力時に「計画月」を入力したタイミングで更新後処理イベントを使って
これで、ケアプランが存在しない場合はNullチェックで警告が出せますね
もう一つは、モニタリング入力時にケアプランが存在しなかったデータについて「後から入力する」ことですが、これはケアプラン入力時に更新クエリを発行すればいいでしょう
2.ケアプランIDがない場合、「評価」の入力可否をどのように決めるか
ケアプランIDがある場合は、
DateDiff("m", [計画日], [計画月])
で何か月目なのかが判断できますない(nullの)場合は、「ケアプランが不明です」として入力不可にしてしまうか、推定3か月目等、それでも入力すべきタイミングを計算するかを考える必要があります。後者の場合は、ケアプランの最後のデータを拾ってきて仮の計画日として計算させる形になります
ご連絡ありがとうございます。
「T_モニタリング」に「ケアプランID」を設ける形で再度挑戦してみようと思います。
毎月、記録するT_モニタリングと、計画をするT_ケアプランは記録をする担当者が違う為、ケアプランが期日を過ぎてもモニタリングは毎月可動するように考えています。(過ぎている場合警告を出す予定で)
毎月のモニタリングはお客様数が50名を超えるのでできれば表形式を使いたいと思っています。
クエリの組立が勉強不足なのだと痛感しました。hirotonさんありがとうございます。
テーブル一つで組めば楽だと思いますが
『「評価」は2か月に1度にしよう』とか業務内容変更の可能性なんかを考えるとテーブル1つにしちゃったら発狂間違いなしですねぇ
もう一つ例を挙げているように「T_モニタリング」に「ケアプランID」を設けてあげればクエリで簡単にモニタリングの計画月に対応するケアプランの計画日が拾えるので日付の比較で3か月目かどうかが簡単に計算できます。「評価日」も簡単に計算できるのでフィールドに持つ必要もなさそうです
質問のように対応する「ケアプランID」が不明の状態だと、自前で対応するケアプランの計画日を探すという計算式を組むことになります。結構めんどくさいです
「関係性がよくわからない」とはこの部分のことで、それぞれのテーブルに日付のデータが入っているので頑張れば関係性を見つけることはできそうですが、そんな頑張りせずにIDで紐づけできないか?という話です
「T_モニタリング」に「ケアプランID」を設けて、メインフォーム(T_ケアプラン)、サブフォーム(T_モニタリング)としてプランIDとケアプランIDをリンクさせ、よくあるメイン-サブフォーム形式で組めば難しいものでもないのではないでしょうか
ありがとうございます。説明足らずですみません。
やはりテーブル一つで組むのがよいのでしょうか…
モニタリングというのは毎月報告していく書式ですのでお客様の様子を日付と内容を挿入し毎月更新します。
ケアプランは初回から6か月おきに作る書式です。関連性は、ケアプランで作成した計画が3か月目で毎月行うモニタリングを元に評価する。という点だけです。ただ、毎月行うモニタリングの書式のフォームに評価をする項目も盛り込みたいと考えています。(記録者にわかりやすくしたい為です)
テーブルを一つにまとめて挑戦もしていますが、構成がいまいち頭に描けず混乱しています。
うまくいきました。ありがとうございます!
モニタリングとケアプランの関係性がよくわかりませんね
少し乱暴ですがテーブルを分けずに「T_ケアプラン」に「モニタリング評価1」、「モニタリング評価2」、「その他情報フィールド」をつけてしまえば解決するのでは?
テーブルを分ける必要があるのなら「T_モニタリング」に「ケアプランID」を設けて関係性を持たせれば楽ができると思います
未記入のフィールドにデータを書き込むなら更新クエリです。それともケアプランを作成したときに自動的に「T_モニタリング」にデータを追加したい(6か月分)という内容でしょうか?
あっ、2つのテーブルはちがいますね。kitasueさんの回答でいいと思います。
2行目の
の部分を消せば良いのでは。
ご確認ありがとうございます!上記の教えていただいたSQLは重複無しで使用できておりました、
そのコンボボックスを、もう一つ条件をプラスして(具体的には、もう一つリレーションシップで繋がる別のテーブルの主キーとつながるものだけに絞り込んで表示する)使用しようとしたところ、重複が発生しました。
もしや、今度こそユニオンクエリを使えば良いのですね…?あとでやってみようとおもいます。
hatena様
お世話になっております。
お忙しい中、ご回答して頂き、ありがとうございます。
頂いたヒントを調べながら制作してみます。
難易度がかなり高そうですが(-_-;)、少しずつ勉強しながら頑張ります。
引き続き、今後とも宜しくお願い致します。
検索コンボボックスの選択肢追加 Microsoft Access 掲示板 - zawazawa
の続きですね。
そこで紹介した下記のSQLで重複なしの年月リストになると思いますが、それではダメでしたか。
「N」は演算フィールドに適当な名前を付けたという理解でよろしいです。
私自身、実運用でそのような仕様のものは作ったことがないので、脳内シミュレーションのみで提案してますので、実運用で問題が発生するかもしれませんが、その場合はその都度、修正していくことになると思います。
顧客情報履歴テーブルに移動をした方がいいと思います。また、それだけ変更項目が多いなら、前者の方法がいいと思います。
顧客マスターテーブルに、最新顧客情報履歴CD のフィールドも追加しておくといいでしょう。
顧客情報を更新したときに、その 顧客情報履歴CD でマスターの 最新顧客情報履歴CD を更新するようにVBAで組んでおきます。
顧客情報の最新の情報のみ簡単に抽出できますので。これがないと、DMax関数かサブクエリの複雑なSQLになります。
質問2に関してはVBAが必要になりますね。重複チェックも必要になります。ランダムな値は、rnd関数を使って取得します。この辺はWEB検索で調べてみてください。
質問3は、WEBで探せばありそうな気がします。
あるいは、入社年 と 連番 は別フィールドにして、複数フィールド主キーにするという方法もあります。
こうすると、連番の採番が楽になります。
今、ちょっと時間がないので、とりあえず回答になりましたが、上記をヒントにいろいろ調べてみてください。
kitasue様
モジュールを記載いただきありがとうございます。
頂きましたモジュールで試してみたところ無事思うような動きになりました。
大変助かりました。 本当にありがとうございます。
少しずつ私も勉強していきたいと思います。
今後ともよろしくお願いします。
標準モジュールに以下を定義すると、
f_strInsAfter([説明文],"<img",">","<br>")
がご所望の文字列を返します。
hatena様
すみません。
質問3に誤りがあります。(6月→3月)
修正できなかったので質問3のみ再度書き込みました。
不慣れで大変申し訳ありません。
質問3:
社員コードは入社年と連番の組合せでしたく、年が変わったら連番を001にリセットしたいです。
例:2020年4月~2021年3月まで020001~、2021年4月~2022年3月まで021001~みたいです。
hatena様
早速、ご回答と分かりやすい説明をして頂きありがとうございます。
Accessを勉強し始めたばかりで前者の設計例と後者の設計例どっちがいいのか判断すらまだできません(-_-;)
同じ情報を何回も登録したくないので前者の設計例を参考させながら制作したいと思っております。
テーブル構成は下記を想定しています。(Excelで仮表を作成した程度でAccessでは未作成です。)
テーブル設計で新たに質問がいくつか出てきました。
顧客マスター
顧客コード 主キー (AAAA0001)(AAAA:は任意4文字)(0001:自動ランダム採番)
顧客名
登録日
顧客情報履歴
顧客情報履歴CD 主キー(数値型)
顧客コード
変更日
電話番号
顧客先担当者名
・・・
取引情報
取引情報ID 主キー(数値型)
顧客コード
顧客情報履歴CD
取引日
取引内容
社員コード
・・・・
社員マスター
社員コード 主キー(020001)(020:入社年)(001:連番)
名前
フリガナ
入社日
・・・・
質問1:
顧客マスターテーブルの顧客名も変更される可能性があり、顧客情報履歴テーブルに移動をした方がいいでしょうか。
(顧客マスターテーブルのフィールドが登録日だけになってしまいます。)
質問2:
顧客コードでアルファベット4文字とランダムで自動生成した数値にしたいですが参考している書籍に書いて無く、可能でしょうか。
質問3:
社員コードは入社年と連番の組合せでしたく、年が変わったら連番を001にリセットしたいです。
例:2020年4月~2021年6月まで020001~、2021年4月~2022年6月まで021001~みたいです。
いきなり最初のフィールドのコード設定で躓きましたがご教授の程宜しくお願いします。
現在は書籍を読み続きながらhatena様のサイトの過去の投稿等で勉強させて頂いてます。
ありがとうございます。
色々と質問等出てくるかもですが、どうかご教示の程、宜しくお願い致します。
インポートをやめて、追加クエリを使ったリンクテーブルに修正したら、とても使い勝手が良くなりました。本当に助かりました!
方法としては2つあります。
前者の設計例(一例ですので、実態にあわせて修正の必要あり)
顧客マスター
顧客コード 主キー
顧客名
・・・その他変更の可能性のないフィールド
顧客情報履歴
顧客情報履歴CD 主キー
顧客コード
変更日
電話番号
担当者名
・・・その他変更の可能性あるフィールド
取引情報
取引情報ID 主キー
顧客コード
顧客情報履歴CD
取引日
取引内容
・・・・
顧客情報履歴CD は入力フォームのテキストボックスの規定値に最新値を設定しておく。(DMax関数で)
※顧客情報履歴 は 顧客コード と 顧客サブコード で複数フィールド主キーにする方法もあります。
後者の設計例
顧客マスター
顧客コード 主キー
顧客名
変更日
電話番号
担当者名
・・・・
取引情報
取引情報ID 主キー
顧客情報履歴CD
取引日
取引内容
電話番号 変更の可能性のあるフィールドは重複して持たせる
担当者名 変更の可能性のあるフィールドは重複して持たせる
・・・・
フォームで入力時に、変更の可能性のあるデータは、VBAでマスターの値を代入する。
ありがとうございます。参考にさせていただきます。
リンクテーブルから追加クエリを作成すればよいのですね。よくわかりました。この方法でやっていきたいと思います。ありがとうございました。
クエリで関数を使わなくても、フォームのテキストボックスの書式に、
0000¥/00¥/00
と指定すれば、表示されます。
編集もできますが、編集時は、
/
は消えます。
元データは何で、どのように取り込んでますか。
自分なら下記のような方法をとります。
元データはリンクテーブルにする。
Access側のテーブルのフィールドは日付/時刻型にしておく。
リンクテーブルから追加クエリを作成して、追加クエリのフィールドで Format([年月日],"0000/00/00") と変換しておく。
追加クエリを実行すれば、日付/時刻型として取り込めるので、あとは書式設定で、好きな書式で表示できます。