Private Sub 部品F閉ボタン_click()
If Me.Dirty Then
If MsgBox("データが変更されています。保存して終了しますか?", vbYesNo) = vbNo Then
Exit Sub
Else
Me.BeforeUpdate = "" 'キャンセル無効
DoCmd.RunCommand acCmdSaveRecord
'DoCmd.RunCommand acCmdRefresh
Me.BeforeUpdate = "[イベント プロシージャ]" 'キャンセル有効
Call UserLog("MNFCT", "Update")
End If
End If
DoCmd.Close
End Sub
メインフォームの方はこのように
Private Sub 終了ボタン_Click()
On Error GoTo ErrHandler
If SysCmd(acSysCmdGetObjectState, acForm, "F_部品") <> 0 Then
Forms!F_部品.終了ボタン_Click
End If
If SysCmd(acSysCmdGetObjectState, acForm, "F_製品") <> 0 Then
Forms!F_製品.終了ボタン_Click
End If
DoCmd.Quit acQuitPrompt
ErrHandler:
End Sub
Private Sub Form_Close()
If Me.Dirty Then
If MsgBox("データが変更されています。保存して終了しますか?", vbYesNo) = vbNo Then
Exit Sub
Else
Me.BeforeUpdate = "" 'キャンセル無効
DoCmd.RunCommand acCmdSaveRecord
'DoCmd.RunCommand acCmdRefresh
Me.BeforeUpdate = "[イベント プロシージャ]" 'キャンセル有効
Call UserLog("MNFCT", "Update")
End If
End If
End Sub
Dim fileName As String
fileName = Dir(testPath)
Name testPath As Left(testPath, Len(testPath) - Len(fileName)) & Replace(fileName, "☆", "★")
起こりうること全部チェックするなら
Dim fileName As String
Dim folderPath As String
fileName = Dir(testPath)
folderPath = Left(testPath, Len(testPath) - Len(fileName))
fileName = Replace(fileName, "☆", "★")
If Dir(testPath) = "" Then
'元ファイルが存在しません
ElseIf Dir(folderPath & fileName) <> "" Then
'変更後のファイル名がすでに存在します
Else
On Error Resume Next
Name testPath As folderPath & fileName
If Err <> 0 Then
'予期せぬエラーが発生しました
End If
On Error Goto 0
End If
Private Sub PDF表示_Click()
Dim PDFPath As String, FldPath As String
PDFPath = Application.CurrentProject.Path & "\PDFDATA\" & MNFCTID & ".pdf"
FldPath = Application.CurrentProject.Path & "\PDFDATA"
If Not Dir(PDFPath) = "" Then
Shell "C:\Windows\explorer.exe " & PDFPath, vbNormalFocus
Else
MsgBox "データを探せませんでした。" & Chr(13) _
& "PDFフォルダを開きます。"
Shell "C:\Windows\explorer.exe " & FldPath, vbNormalFocus
End If
End Sub
まさにその通りです!返信ありがとうございました!
FileName = Left(CurrentDb.Name, InStrRev(CurrentDb.Name, "¥")) & "総務部¥物品要求書.xls"
赤文字のところを付け加えました。
これでいかかでしょうか?
連投失礼します。半角「\」が投稿時に「/」になってしまいました。
& "物品要求書.xls"
↓
& "総務部¥物品要求書.xls"
自己解決しました!
以下の修正でできました。よく考えたらシンプルにパス記述を
考えるべきだったんですね。
お騒がせしました。
& "物品要求書.xls"
↓
& "総務部\物品要求書.xls"
ありがとうございます。
とりあえず、通常通りの操作であれば問題なく動くようにした状態まで
もっていってから、フォームを分ける用に変えていきたいと思います。
(本格的に変えていくのは新年からとなると思いますが)
フォームの更新前処理の条件式や、フォーム構成なども見直す方向で
考えていきたいと思います。
本当にありがとうございます!
ちなみに、>> 5が微妙な書き方なのは、このような処理を考えるとドツボにはまるからです。(本当にやりたいことは別なのに)
BeforeUpdate
でCancel = True
したいがためだけに閉じるときに更新前処理をキャンセルすると出るメッセージを変更(hatena chipsさん)
こんな処理考えるくらいなら
これの要求を整理して、メニューに編集用、閲覧用2つボタン置く形じゃダメなの?とかの方向性を考えたほうがよっぽど建設的です
理想の運用ならそれでいいと思いますが、フォームって予期せぬ閉じ方をされるんですよね
フォーム右上の×をクリックされたり(非表示にできるので何とかなる)、ACCESS本体の右上の×をクリックされたり(本体の表示をしない方法があるので何とかなる)、タスクバーから終了されたり、タスクマネージャーから強制終了されたり・・・
なので、実際にデータが決定されるタイミング(BeforeUpdate)で内容を決めましょう。という話です
こうしておけば、どのような形でフォームが閉じられてもBeforeUpdateイベントを通るので保存内容の確認ができます
毎度、手取り足取り本当にありがたいです。
Dirtyは、開いてないと使えないヨ、くらいしか知識が無かったので
Syscmdも有効活用していきたいと思います!
ありがとうございます…!
まだまだイベントのタイミングがうまくつかめていないので、
その部分についてももう一度勉強しなおしてみようと思います。
また、部品フォームのDirty部分なんですが、以下のような形にしました。
メインフォームの方はこのように
SysCmdを用いた、hirotonさんの方法でなく、上記のようなものでも
今回の件については問題なく動きますでしょうか?
とりあえず
フォームの状態を知るには?(T'sWareさん)
質問のコードを次のように変更すれば動作はすると思います
フォームが開いているかどうかをチェックし、開いているときに限りDirtyプロパティをチェックすれば良いということですね
データの更新自体は様々なタイミングで発生します。フォームを閉じるというアクションを取った場合は、Closeイベントの前にBeforeUpdateイベントが発生し、BeforeUpdateイベントが終わると保存内容が決定されます
(実際にはもっと様々なイベントが発生します)
イベントは1つのアクションに対して連鎖的に複数発生する場合があるので、どのイベントで処理するか適切に判断する必要があります
Closeイベントの時点ではすでにデータが決定されてしまっているので、そこで保存するかどうかの確認や、再度データを変更・保存しなおすような処理はすべきではありません
「データの更新処理が済んでないうちはフォームを閉じる処理をしてはいけない」という意味で、修正しようとした内容よりも質問時点でのコードのほうが考え方が正しいです
ありがとうございます。
都合により、データの閲覧と編集を同じフォームで行っています。
(フォームを分けるという理解を得られていない為、これは変更できなさそうです)
データ編集ユーザ用に、保存ボタンや編集クリアボタン等を配置しています。
しかし、データを見るだけのつもりのユーザーが誤って一部のデータを変更し、
それに気が付かぬまま(=編集クリアボタン等を押さぬまま)フォームを
閉じようとする際(およびレコード移動する際)に、MSGBOXで警告するようにしています。
フォームはマスタテーブルをレコードソースとしており、フォーム内の
TXTBOXを変更した際に、すぐテーブル内容が書き換わってしまわないように、
としています。
根本的にデータ更新タイミングなどが間違っているということでしょうか…
よくわからないんですが、編集(変更)したのに保存したくない場合があるんですか?
データの保存(する/しない)と、フォームを閉じるは、直接的には無関係です。変更中の内容をどうこうしたいなら更新前処理で制御すべきでしょう
ありがとうございます。
結構いじっているのに、理解できていないことが多いですね。
本年、一年お世話になりました。また来年よろしくお願いします。
お早いご返信、ありがとうございます。
前に1度、部品フォームを変えてから閉じて、メインフォームを閉じようとしたら閉じれなかった
と他の人から連絡を受けたため、このような形になっていました。
しかし、考えてみると、確かにご指摘通りへんてこりんですね…。
申し訳ありません。
MSGBOXの出現も、いろいろ試したところ、フォーム開きっぱなしの時だけでした。
部品フォームを閉じるときに、以下のようにすれば問題ないでしょうか…?
以上、よろしくお願いいたします。
そもそも、これが勘違いではないでしょうか。
フォームを閉じる時に、もしレコードが更新されていたら、自動的に保存されて、Dirtyプロパティはリセットされます。
DoCmd.OpenForm "F_部品" で開いた直後、DirtyプロパティはFalseになっているはずです。
もし、「データ変更云々のメッセージを表示」のメッセージが出るなら、フォームを開く時、読み込み時、レコード移動時、、などで、レコードを更新する処理が記述されていることになります。
フォームBを閉じたタイミングで、フォームAの方でコードを実行したい、ということだとすると、
DoCmd.OpenForm の直後に実行したいコードを記述すればOKです。
フォームAのコマンド1のクリックでフォームBを開くとして、
元の質問は解決済みで、別の質問になると思いますので、新規に質問しなおしてください。
そのときに、何をどのように合算するのか具体的に説明するようにしてください。
最初はこんな感じでした。
[T_商品]
参照整合や連鎖更新をあきらめれば、機能します。
テーブルを分割して運用する方法がイメージがつかないです。
[T_商品]
[T_パッケージ]
-
T_商品テーブルという、ごちゃまぜのテーブルを作ってほうが
データ入力時にすべて同じテーブルを呼び出すだけで簡単かと思ったのですが、
属性ごとに別のテーブルを用意したほうが今になってよかったのかと思っています。
合算して抽出する方法ご教示お願いいたします
これだけの情報では回答するのは難しいですね。
現状のテーブルと、そのデータ例を提示して、具体例で説明してもらえると回答できるかも知れません。
年末の忙しさも相まって、なかなか参考サイトを絞り込めずにいましたので非常に助かりました。
ありがとうございます。後程じっくり確認してみます!
今、ちょうど同じくACCESSの共有化等を検討しています。
もうご覧になっているかもしれませんが、こちらのサイト
に大変お世話になっていますので紹介しておきます。
mindwoodさん https://qiita.com/mindwood/items/062cde46b848d0c9e96a
詳しく解析していただき、ありがとうございます。
元のファイルを開いている等については考えていませんでした。
次にエラーが起きたとき、改めて確認したいと思います。
エラー対応のコードも組み込みたいと思います。ありがとうございます!
教えていただいた通りの方法で、希望のデータが作成できました!
自分では全く想像がつかなかった方法で、大変勉強になりました。
素早く教えていただけて本当に助かりました。ありがとうございました!
できました。リレーションシップで同じテーブルを複数登録できるのにはこういう意味があったのですね。
ありがとうございました。
いろいろありますが、SQLと連番テーブルを使う方法を紹介します。
まず、下記のようなテーブルを作成します。
テーブル名 T_連番
フィールド 連番 (数値型)
連番フィールドに 0から始まる連番を入力しします。予想される一人当たりの最大件数まで入力してください。
クエリを新規作成して、現在のテーブルと上記のT_連番を追加します。
クエリのデザインビューで下記のように設定します。
SQL文なら下記になります。
これでご希望のデータになります。
フォームも完成しました。
「1回の食事で1種類」でいいのなら、T_献立_料理 は不要になります。
T_献立 に 料理ID を追加すればいいでしょう。
T_献立
献立ID 主キー オートナンバー型
日付
料理ID
種別 (朝食、昼食、夕食など)
T_献立 をレコードソースとする入力フォームを作成すればいいでしょう。
料理IDはコンボボックスにして、料理名で選択できるようにしてもいいでしょう。
コンボボックスを2つ並べてIDでも料理名でも入力できるようにすることも可能です。
コードでも名称でも入力できるコンボボックス - hatena chips
リレーションシップ画面で、T_商品 と T_クラスマスタ を追加しで、クラス と クラスID を結合して「参照整合性」にチェックを入れます。ここまではできていますよね。
次に、テーブルの追加で、もう一回、 T_クラスマスタを追加します。 T_クラスマスタ_1 と別名がついて追加されます。
T_商品 と T_クラスマスタ_1 間で クラス と クラスID を結合して「参照整合性」にチェックを入れればいいでしょう。
お礼を返すのを忘れておりました。うまくいきました。ありがとうございました。
もしかして:
起こりうること全部チェックするなら
たとえば
testPath
が「C:\☆★☆注目☆★☆\☆hoge.dat
」だと変換後のパスは「C:\★★★注目★★★\★hoge.dat
」となります。大抵そんなフォルダないよって感じでエラーになります。もしかしませんか?あと、当たり前だけど
testPath
に"☆"
が含まれていないとName testPath As testPath
になるんでエラーになります最初のコードも2番目のコードもやっていること自体を変えている(ファイル名のみ
Replace
の対象とする)ので、フォルダ名も変換されるのが正しい処理なら最初のコードはもしかしません。2番目のコードにはフォルダの存在チェック処理を追加する必要があります予期せぬエラーについてはhatenaさん指摘の元ファイルが開いている場合の他、アクセス権の問題(書き込み許可がない)とかもあり得ます
システムでどこまで保証されているかによって必要なエラー対策は変わります。やりたいこととやっていることをもう一度見直して必要な処理を見極めてください
Name ステートメント (VBA) | Microsoft Docs
上記によると、エラーになる原因としては、下記の2点が考えられます。
それ以外のエラーについてはちょっと分かりません。
ありがとうございます。しかし、今回商品詳細ページを直に開く場合があるんでした。。
エラートラップオプションについて確認してみます。
1回の食事で1種類、30日分です。
質問のコードには4つの変数が含まれています。それぞれ中身はなんですか?
これに対してテストコードはきちんと同様の内容になっていますか?
DDEExecute
はどうやらExcel4.0マクロのコマンドが使えるようです。Workbook.Move
はシート移動のコマンドのようですテストコードは
としたら動作しませんか?
1回の食事の献立で、料理は必ず一種類だけ、ということてすか。
もし、そうなら、T_献立_料理 テーブルは不必要になります。
T_献立 に 料理ID フィールドを持たせるだけです。
そうでないなら(ふつうは複数の料理がでると思いますが)、
T_献立_料理 は必要です。
献立の入力フォームの作成について、これから解説しますが、今はちょっと忙しいので、今日の夜ぐらいになりますので、しばらくお待ちください。
分かりやすい説明ありがとうございます。全て真似事ですが作成できました。やはり献立が今一理解できません。12月17日の夕食の献立にカレー、サラダがある。仮にカレーしかなければ、毎日一食限定なら必要はないのでしょうか?献立はオートナンバーになっているので、12月17日はカレーとサラダだったと言うことがデータから分かると言うことなのでしょうか?簡単に2種類の料理名と材料名を入力しました。次はどうすればいいでしょうか?
丁寧な解説、ありがとうございます。本当に助かります。
ユーザーに多少の手間を取らせてしまいますが、とりあえず元データの
整理が完了するまでは、合致するデータが無かった場合に
該当するフォルダを開くようにします。
また、データ整理・および新たなデータを一気に登録する際には
改めてデータの参照方法を考えてみます。
本当に長々とお付き合いくださりありがとうございました。
良くない案1
フォルダをエクスプローラーで開く
良くない案2
ファイル名で近似値を求めてそのファイルを開く
例えば「B030b」を開こうとした場合、ファイルの一覧を降順に捜査して
の比較でそれっぽいファイルを見つけることはできます
複雑なことをしようとすればするほどさらなるイレギュラーが出たときに「思っていたのと違う。不具合だ」と言われるものです。全然いいアイディアになりません
本当の「いいアイディア」はPDFファイルを分割して保存しなおすことができないかを検討し、評価することでしょう
とはいっても、システムの運用開始はなるべく早くという要件もあるでしょうから、「製品ID.pdf」が見つからなかった場合はメッセージボックスを表示して(上記案のような)追加操作の実行を促す仕組みとすることはあると思います
過去の遺産の整理と並行して運用できるような限定的な仕組みという位置付けの機能としてしまいましょう
このテーブルから入力フォームを作成していくことになります。
まずは、料理に必要な材料を入力するフォームから作成していきましょう。
が、その前に、テーブルのフィールドにルックアップの設定をしておきましょう。
まず、T_料理 の「種別」フィールドのルックアップを下図のように設定します。
値集合ソースは
主菜;副菜;汁物
というようにセミコロンで区切ってリストを入力してください。これで、コンボボックスから選択できるようになります。
次に、T_料理_材料の「材料ID」フィールドのルックアップの設定を下図のようにします。
値集合タイプを「テーブル/クエリ」にして値集合ソースは「T_材料」とします。
列数: 2、列幅: 0 と設定することでコンボボックスのリストには「T_材料」の2番目のフィールドの材料名が表示されることになります。
テキストボックス部分にも材料名が表示されます。ただし、フィールドに実際に格納されている値は、材料IDになります。
この辺の設定の意味は理解するのが難しいと思いますが、おいおい理解できるようになるでしょう。
この設定でテーブルでの材料の入力が下記のようにコンボボックスから選択することできるようになります。