Microsoft Access 掲示板

6,622 件中 4,481 から 4,520 までを表示しています。
4
名前なし 2020/12/27 (日) 18:25:57 8b661@ce856

まさにその通りです!返信ありがとうございました!

3
おか。 2020/12/27 (日) 12:51:21 31438@cab8e

FileName = Left(CurrentDb.Name, InStrRev(CurrentDb.Name, "¥")) & "総務部¥物品要求書.xls"
赤文字のところを付け加えました。
これでいかかでしょうか?

2
鉄血 2020/12/27 (日) 11:57:02 43d60@ce856

連投失礼します。半角「\」が投稿時に「/」になってしまいました。


                   & "物品要求書.xls"

                   & "総務部¥物品要求書.xls"

1
鉄血 2020/12/27 (日) 11:55:04 43d60@ce856

自己解決しました!
以下の修正でできました。よく考えたらシンプルにパス記述を
考えるべきだったんですね。
お騒がせしました。


                   & "物品要求書.xls"

                   & "総務部\物品要求書.xls"

9
ゲッキョク駐車場 2020/12/26 (土) 08:35:51 cb55f@f6500

ありがとうございます。

とりあえず、通常通りの操作であれば問題なく動くようにした状態まで
もっていってから、フォームを分ける用に変えていきたいと思います。
(本格的に変えていくのは新年からとなると思いますが)

フォームの更新前処理の条件式や、フォーム構成なども見直す方向で
考えていきたいと思います。

本当にありがとうございます!

8
hiroton 2020/12/25 (金) 17:13:20 ca77e@f966d

ちなみに、>> 5が微妙な書き方なのは、このような処理を考えるとドツボにはまるからです。(本当にやりたいことは別なのに)BeforeUpdateCancel = Trueしたいがためだけに

閉じるときに更新前処理をキャンセルすると出るメッセージを変更(hatena chipsさん)

こんな処理考えるくらいなら

都合により、データの閲覧と編集を同じフォームで行っています。
(フォームを分けるという理解を得られていない為、これは変更できなさそうです)

これの要求を整理して、メニューに編集用、閲覧用2つボタン置く形じゃダメなの?とかの方向性を考えたほうがよっぽど建設的です

7
hiroton 2020/12/25 (金) 16:48:44 ca77e@f966d >> 6

理想の運用ならそれでいいと思いますが、フォームって予期せぬ閉じ方をされるんですよね
フォーム右上の×をクリックされたり(非表示にできるので何とかなる)、ACCESS本体の右上の×をクリックされたり(本体の表示をしない方法があるので何とかなる)、タスクバーから終了されたり、タスクマネージャーから強制終了されたり・・・

なので、実際にデータが決定されるタイミング(BeforeUpdate)で内容を決めましょう。という話です

Private Sub Form_BeforeUpdate(Cancel As Integer)
  If (保存しない条件) Then Cancel = True
End Sub

こうしておけば、どのような形でフォームが閉じられてもBeforeUpdateイベントを通るので保存内容の確認ができます

6
ゲッキョク駐車場 2020/12/25 (金) 16:07:41 修正 cb55f@f6500

毎度、手取り足取り本当にありがたいです。

Dirtyは、開いてないと使えないヨ、くらいしか知識が無かったので
Syscmdも有効活用していきたいと思います!
ありがとうございます…!
まだまだイベントのタイミングがうまくつかめていないので、
その部分についてももう一度勉強しなおしてみようと思います。

また、部品フォームのDirty部分なんですが、以下のような形にしました。

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

SysCmdを用いた、hirotonさんの方法でなく、上記のようなものでも
今回の件については問題なく動きますでしょうか?

5
hiroton 2020/12/25 (金) 15:34:54 ca77e@f966d

とりあえず
フォームの状態を知るには?(T'sWareさん)

質問のコードを次のように変更すれば動作はすると思います

  DoCmd.OpenForm "F_部品"
↓
  If SysCmd(acSysCmdGetObjectState, acForm, "F_部品") <> 0 Then
(中略)
  End If

フォームが開いているかどうかをチェックし、開いているときに限りDirtyプロパティをチェックすれば良いということですね


根本的にデータ更新タイミングなどが間違っているということでしょうか

データの更新自体は様々なタイミングで発生します。フォームを閉じるというアクションを取った場合は、Closeイベントの前にBeforeUpdateイベントが発生し、BeforeUpdateイベントが終わると保存内容が決定されます
(実際にはもっと様々なイベントが発生します)

イベントは1つのアクションに対して連鎖的に複数発生する場合があるので、どのイベントで処理するか適切に判断する必要があります

Closeイベントの時点ではすでにデータが決定されてしまっているので、そこで保存するかどうかの確認や、再度データを変更・保存しなおすような処理はすべきではありません

「データの更新処理が済んでないうちはフォームを閉じる処理をしてはいけない」という意味で、修正しようとした内容よりも質問時点でのコードのほうが考え方が正しいです

4
ゲッキョク駐車場 2020/12/25 (金) 14:19:18 修正 cb55f@f6500 >> 3

ありがとうございます。

都合により、データの閲覧と編集を同じフォームで行っています。
(フォームを分けるという理解を得られていない為、これは変更できなさそうです)

データ編集ユーザ用に、保存ボタンや編集クリアボタン等を配置しています。
しかし、データを見るだけのつもりのユーザーが誤って一部のデータを変更し、
それに気が付かぬまま(=編集クリアボタン等を押さぬまま)フォームを
閉じようとする際(およびレコード移動する際)に、MSGBOXで警告するようにしています。

フォームはマスタテーブルをレコードソースとしており、フォーム内の
TXTBOXを変更した際に、すぐテーブル内容が書き換わってしまわないように、

Private Sub Form_BeforeUpdate(Cancel As Integer)
  Cancel = True
End Sub

としています。

根本的にデータ更新タイミングなどが間違っているということでしょうか…

3
hiroton 2020/12/25 (金) 13:35:17 ca77e@f966d

よくわからないんですが、編集(変更)したのに保存したくない場合があるんですか?

データの保存(する/しない)と、フォームを閉じるは、直接的には無関係です。変更中の内容をどうこうしたいなら更新前処理で制御すべきでしょう

2
nokonoko 2020/12/25 (金) 09:21:39 653a6@54883

ありがとうございます。
結構いじっているのに、理解できていないことが多いですね。
本年、一年お世話になりました。また来年よろしくお願いします。

2
ゲッキョク駐車場 2020/12/25 (金) 08:57:15 修正 cb55f@f6500 >> 1

お早いご返信、ありがとうございます。
前に1度、部品フォームを変えてから閉じて、メインフォームを閉じようとしたら閉じれなかった
と他の人から連絡を受けたため、このような形になっていました。
しかし、考えてみると、確かにご指摘通りへんてこりんですね…。
申し訳ありません。
MSGBOXの出現も、いろいろ試したところ、フォーム開きっぱなしの時だけでした。

部品フォームを閉じるときに、以下のようにすれば問題ないでしょうか…?

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

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

1

これで、うっかりデータを変更しちゃってフォームを閉じちゃった際にも、
データ変更云々のメッセージを表示できるようになりました。

そもそも、これが勘違いではないでしょうか。
フォームを閉じる時に、もしレコードが更新されていたら、自動的に保存されて、Dirtyプロパティはリセットされます。
DoCmd.OpenForm "F_部品" で開いた直後、DirtyプロパティはFalseになっているはずです。

もし、「データ変更云々のメッセージを表示」のメッセージが出るなら、フォームを開く時、読み込み時、レコード移動時、、などで、レコードを更新する処理が記述されていることになります。

1
hatena 2020/12/24 (木) 22:16:12 修正

フォームBを閉じたタイミングで、フォームAの方でコードを実行したい、ということだとすると、
DoCmd.OpenForm の直後に実行したいコードを記述すればOKです。

フォームAのコマンド1のクリックでフォームBを開くとして、

Private Sub コマンド1_Click()
    DoCmd.OpenForm "フォームB", windowmode:=acDialog

    'ここにやりたい処理を書けばよい
    '例えばメッセージを表示させるなら
    MsgBox "フォームBを閉じました"

End Sub
17

元の質問は解決済みで、別の質問になると思いますので、新規に質問しなおしてください。

そのときに、何をどのように合算するのか具体的に説明するようにしてください。

3
nokonoko 2020/12/24 (木) 10:35:02 653a6@54883

最初はこんな感じでした。
[T_商品]

商品ID(キー)属性ID商品名
1  1商品45リンゴジャム
21商品3 5小女子の佃煮
33資材NullNull 丸瓶(短)
43資材NullNull丸瓶(中)
53資材NullNull丸瓶(蓋)
62原料NullNull砂糖

参照整合や連鎖更新をあきらめれば、機能します。
テーブルを分割して運用する方法がイメージがつかないです。

2
nokonoko 2020/12/24 (木) 09:44:11 653a6@54883

[T_商品]

商品ID(キー)属性IDパッケージID商品名
1  1商品2リンゴジャム
21商品1  小女子の佃煮
33資材Null丸瓶(短)
43資材Null丸瓶(中)
53資材Null丸瓶(蓋)
62原料Null砂糖

[T_パッケージ]

パッケージID(キー)パッケージ名資材ID1資材ID2
1  丸瓶(短セット)35
2丸瓶(中セット)4  5

-

T_商品テーブルという、ごちゃまぜのテーブルを作ってほうが
データ入力時にすべて同じテーブルを呼び出すだけで簡単かと思ったのですが、
属性ごとに別のテーブルを用意したほうが今になってよかったのかと思っています。

16

合算して抽出する方法ご教示お願いいたします

1

これだけの情報では回答するのは難しいですね。
現状のテーブルと、そのデータ例を提示して、具体例で説明してもらえると回答できるかも知れません。

2
どんぐり 2020/12/23 (水) 13:31:08 修正 0029a@1c915 >> 1

年末の忙しさも相まって、なかなか参考サイトを絞り込めずにいましたので非常に助かりました。
ありがとうございます。後程じっくり確認してみます!

1
ゲッキョク駐車場 2020/12/23 (水) 11:27:39 cb55f@f6500

今、ちょうど同じくACCESSの共有化等を検討しています。

もうご覧になっているかもしれませんが、こちらのサイト
に大変お世話になっていますので紹介しておきます。

mindwoodさん https://qiita.com/mindwood/items/062cde46b848d0c9e96a

4
トマト 2020/12/23 (水) 10:28:08 0029a@1c915 >> 3

詳しく解析していただき、ありがとうございます。
元のファイルを開いている等については考えていませんでした。
次にエラーが起きたとき、改めて確認したいと思います。
エラー対応のコードも組み込みたいと思います。ありがとうございます!

2
enokidake 2020/12/22 (火) 12:02:52 d37ef@7f037

教えていただいた通りの方法で、希望のデータが作成できました!
自分では全く想像がつかなかった方法で、大変勉強になりました。
素早く教えていただけて本当に助かりました。ありがとうございました!

2
nokonoko 2020/12/22 (火) 10:20:51 653a6@54883

できました。リレーションシップで同じテーブルを複数登録できるのにはこういう意味があったのですね。
ありがとうございました。

1

いろいろありますが、SQLと連番テーブルを使う方法を紹介します。

まず、下記のようなテーブルを作成します。

テーブル名 T_連番
フィールド 連番 (数値型)

連番フィールドに 0から始まる連番を入力しします。予想される一人当たりの最大件数まで入力してください。

クエリを新規作成して、現在のテーブルと上記のT_連番を追加します。
クエリのデザインビューで下記のように設定します。

フィールド名前支給日: DateAdd("m",[連番],[開始日])金額連番
テーブルT_支給T_支給T_連番
表示
並べ替え昇順昇順
抽出条件<=DateDiff("m",[開始日],[終了日])

SQL文なら下記になります。

SELECT T_支給.ID, T_支給.名前, DateAdd("m",[連番],[開始日]) AS 支給日, T_支給.金額
FROM T_支給, T_連番
WHERE T_連番.連番<=DateDiff("m",[開始日],[終了日])
ORDER BY T_支給.名前, T_連番.連番;

これでご希望のデータになります。

15
なお 2020/12/21 (月) 19:55:31

フォームも完成しました。

14

「1回の食事で1種類」でいいのなら、T_献立_料理 は不要になります。

T_献立 に 料理ID を追加すればいいでしょう。

T_献立
 献立ID 主キー オートナンバー型
 日付
 料理ID
 種別 (朝食、昼食、夕食など)

T_献立 をレコードソースとする入力フォームを作成すればいいでしょう。
料理IDはコンボボックスにして、料理名で選択できるようにしてもいいでしょう。

コンボボックスを2つ並べてIDでも料理名でも入力できるようにすることも可能です。

コードでも名称でも入力できるコンボボックス - hatena chips

1
hatena 2020/12/21 (月) 15:42:17 修正

リレーションシップ画面で、T_商品 と T_クラスマスタ を追加しで、クラス と クラスID を結合して「参照整合性」にチェックを入れます。ここまではできていますよね。

次に、テーブルの追加で、もう一回、 T_クラスマスタを追加します。 T_クラスマスタ_1 と別名がついて追加されます。
T_商品 と T_クラスマスタ_1 間で クラス と クラスID を結合して「参照整合性」にチェックを入れればいいでしょう。

画像1

2
nokonoko 2020/12/21 (月) 11:11:25 653a6@54883

お礼を返すのを忘れておりました。うまくいきました。ありがとうございました。

3
hiroton 2020/12/19 (土) 23:59:56 23396@358c8

もしかして:

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

たとえばtestPathが「C:\☆★☆注目☆★☆\☆hoge.dat」だと変換後のパスは「C:\★★★注目★★★\★hoge.dat」となります。大抵そんなフォルダないよって感じでエラーになります。もしかしませんか?

あと、当たり前だけどtestPath"☆"含まれていないとName testPath As testPathになるんでエラーになります

最初のコードも2番目のコードもやっていること自体を変えている(ファイル名のみReplaceの対象とする)ので、フォルダ名も変換されるのが正しい処理なら最初のコードはもしかしません。2番目のコードにはフォルダの存在チェック処理を追加する必要があります

予期せぬエラーについてはhatenaさん指摘の元ファイルが開いている場合の他、アクセス権の問題(書き込み許可がない)とかもあり得ます

システムでどこまで保証されているかによって必要なエラー対策は変わります。やりたいこととやっていることをもう一度見直して必要な処理を見極めてください

2

Name ステートメント (VBA) | Microsoft Docs

上記によると、エラーになる原因としては、下記の2点が考えられます。

newpathname には、既存のファイル名は指定できません。

開いているファイルに Name を使用すると、エラーが発生します。

それ以外のエラーについてはちょっと分かりません。

3
トマト 2020/12/18 (金) 19:26:53 0029a@1c915

ありがとうございます。しかし、今回商品詳細ページを直に開く場合があるんでした。。
エラートラップオプションについて確認してみます。

13
なお 2020/12/18 (金) 16:00:43

1回の食事で1種類、30日分です。

1
hiroton 2020/12/18 (金) 14:29:23 5bcaf@f966d

質問のコードには4つの変数が含まれています。それぞれ中身はなんですか?

ch = ?
sheet_name = ?
book_name = ?
sheet_cnt = ?
DDEExecute ch, "[Workbook.Move(""" + sheet_name + """,""" + book_name + """," + sheet_cnt + ")]"

これに対してテストコードはきちんと同様の内容になっていますか?

DDEExecuteはどうやらExcel4.0マクロのコマンドが使えるようです。Workbook.Moveはシート移動のコマンドのようです
テストコードは

DDEExecute ch, "[Workbook.Move(""Sheet2"",""d:\test.xls""," + "2" + ")]"
↓
DDEExecute ch, "[Workbook.Move(""Sheet2"",""test.xls""," + "2" + ")]"

としたら動作しませんか?

12

毎日一食限定なら必要はないのでしょうか?

1回の食事の献立で、料理は必ず一種類だけ、ということてすか。
もし、そうなら、T_献立_料理 テーブルは不必要になります。
T_献立 に 料理ID フィールドを持たせるだけです。

そうでないなら(ふつうは複数の料理がでると思いますが)、
T_献立_料理 は必要です。

献立の入力フォームの作成について、これから解説しますが、今はちょっと忙しいので、今日の夜ぐらいになりますので、しばらくお待ちください。

11
なお 2020/12/18 (金) 12:53:47

分かりやすい説明ありがとうございます。全て真似事ですが作成できました。やはり献立が今一理解できません。12月17日の夕食の献立にカレー、サラダがある。仮にカレーしかなければ、毎日一食限定なら必要はないのでしょうか?献立はオートナンバーになっているので、12月17日はカレーとサラダだったと言うことがデータから分かると言うことなのでしょうか?簡単に2種類の料理名と材料名を入力しました。次はどうすればいいでしょうか?

10
ゲッキョク駐車場 2020/12/18 (金) 11:20:27 cb55f@f6500 >> 9

丁寧な解説、ありがとうございます。本当に助かります。

ユーザーに多少の手間を取らせてしまいますが、とりあえず元データの
整理が完了するまでは、合致するデータが無かった場合に
該当するフォルダを開くようにします。

また、データ整理・および新たなデータを一気に登録する際には
改めてデータの参照方法を考えてみます。

本当に長々とお付き合いくださりありがとうございました。

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
9
hiroton 2020/12/18 (金) 10:36:12 bcbb2@f966d >> 8

良くない案1
フォルダをエクスプローラーで開く

良くない案2
ファイル名で近似値を求めてそのファイルを開く
例えば「B030b」を開こうとした場合、ファイルの一覧を降順に捜査して

name = "B030b" & "あ"
"B150.pdf" < name => False
"B001~149.pdf" < name => True

の比較でそれっぽいファイルを見つけることはできます


複雑なことをしようとすればするほどさらなるイレギュラーが出たときに「思っていたのと違う。不具合だ」と言われるものです。全然いいアイディアになりません

本当の「いいアイディア」はPDFファイルを分割して保存しなおすことができないかを検討し、評価することでしょう

とはいっても、システムの運用開始はなるべく早くという要件もあるでしょうから、「製品ID.pdf」が見つからなかった場合はメッセージボックスを表示して(上記案のような)追加操作の実行を促す仕組みとすることはあると思います
過去の遺産の整理と並行して運用できるような限定的な仕組みという位置付けの機能としてしまいましょう

10

このテーブルから入力フォームを作成していくことになります。
まずは、料理に必要な材料を入力するフォームから作成していきましょう。

が、その前に、テーブルのフィールドにルックアップの設定をしておきましょう。

まず、T_料理 の「種別」フィールドのルックアップを下図のように設定します。

画像1

値集合ソースは 主菜;副菜;汁物 というようにセミコロンで区切ってリストを入力してください。
これで、コンボボックスから選択できるようになります。

次に、T_料理_材料の「材料ID」フィールドのルックアップの設定を下図のようにします。

画像1

値集合タイプを「テーブル/クエリ」にして値集合ソースは「T_材料」とします。
列数: 2、列幅: 0 と設定することでコンボボックスのリストには「T_材料」の2番目のフィールドの材料名が表示されることになります。
テキストボックス部分にも材料名が表示されます。ただし、フィールドに実際に格納されている値は、材料IDになります。
この辺の設定の意味は理解するのが難しいと思いますが、おいおい理解できるようになるでしょう。

この設定でテーブルでの材料の入力が下記のようにコンボボックスから選択することできるようになります。

画像1