Microsoft Access 掲示板

views
4 フォロー
6,349 件中 1,761 から 1,800 までを表示しています。
3
すずやん 2023/06/16 (金) 08:04:43

>りんご様
ご回答ありがとうございます。申し訳ないのですが書いてある内容がよく理解できませんでした。

>hatena様
ご教授ありがとうございます。教えていただいた方法で実現できそうです!こちらで試してみたいと思います。

5
wazawaza 2023/06/16 (金) 07:38:32

hatenaさん
チョット変化しましたので報告します。
ココが原因なのかな?と薄々思っていたのですが...。

自動採番する仕組みとなっておりまして...

'##############################
'### レコード移動時のID採番 ###
'##############################

Private Sub Form_Current()

    Me.btn_最新ID取得.Enabled = True  '「btn最新ID取得」を使用可能に
    Me.btn_追加.Enabled = False       '「btn追加」を使用不可に(最新ID取得に導く仕掛け)
    
    Const prefix As String = "L"  '「Laminate」の頭文字 "L"
    
    Dim maxID As String
    maxID = DMax("fld_依頼ID", "T_依頼")  '最終IDを取り出す
    
    Dim lastNum As Long
    lastNum = Replace(maxID, prefix, "")  '最終IDから頭文字"L"を除き、数値型へ代入する
    
    Dim newID As String
    newID = prefix & Format(lastNum + 1, "000000")  '+1して桁を揃えて頭文字"L"と結合
    
    Me.txt_依頼ID.DefaultValue = "'" & newID & "'"  '既定値へ代入

End Sub

という具合になっていますが
試しに、ココに Me.[txt_依頼ID].Value = OpenArgs を入れると
採番は出来なくなる一方、fld_依頼IDをダブルクリックすると代入できる
ようになりました。

自動採番の機能を残しつつ、代入の方法はありますか?

4
wazawaza 2023/06/16 (金) 00:21:10

hatenaさん、早速ご対応頂きありがとうございます。
ご指摘のところを、何度も確認しましたが、
変化がありません。

「F_依頼一覧」の「fld_依頼ID」でのダブルクリックのイベントプロシージャは

Private Sub fld_依頼ID_DblClick(Cancel As Integer)
   DoCmd.OpenForm "F_依頼入力", , , , , acDialog, Me.fld_依頼ID.Value
End Sub

に、入力ミスはありますか?
何度もスミマセン。

3

「F_依頼入力」フォームをデザインビューで開いて、プロパティシートのイベントタブの「開くとき」に
[イベント プロシージャ]
と設定されてますか。
もし、設定されていない場合は、ドロップダウンリストから選択して設定してください。

次に、「開くとき」のビルドボタン[...]をクリックして、下記のコードが表示されるか確認してください。

Private Sub Form_Open(Cancel As Integer)
    Me.[txt_依頼ID].Value = OpenArgs
End Sub

下記のように表示されていたら、上記のようになるように真ん中にコードを入力してください。

Private Sub Form_Open(Cancel As Integer)

End Sub

これで、IDが代入されるはずです。

2

hatenaさん、ありがとうございます!
ご提案頂いたコードを入力しましたが、
ダブルクリックしたIDは代入されませんでした。

2

「付箋のような画面」というのがフォームを想定しているなら、
New キーワード を使ってフォームのインスタンスを生成すれば可能です。
下記で似たようなことをしていますので、参考にしてください。

同じフォームを複数表示する - hatena chips

同じフォームを複数表示する その2 - hatena chips

1

acDialog(ダイアログモード)にすると、そのフォームを閉じるか非表示になるまで、次の行のコードは実行されません。
つまり、次の行の
Forms![F_依頼入力]![txt_依頼ID].Value = Me.fld_依頼ID.Value
が実行されるときには、[F_依頼入力]は既に閉じているので、「見つかりません。」というエラーになります。

対処法としてはいろいろありますが、OpenArgs引数で値を渡して、フォームの開くときイベントで代入する方法ですね。

Private Sub fld_依頼ID_DblClick(Cancel As Integer)
   DoCmd.OpenForm "F_依頼入力", , , , , acDialog, Me.fld_依頼ID.Value`
End Sub

F_依頼入力 の開くときイベント

Private Sub Form_Open(Cancel As Integer)
    Me.[txt_依頼ID].Value = OpenArgs
End Sub
1

キークリック(KeyDown)イベント内で、Enterキー押下をSendKeysしたら、それで再びキークリックイベントが発生して、と連鎖して繰り返されることになるのでそうなりますね。

下記のようにフラグを利用して、イベント連鎖を防止して、キー入力をキャンセルしておくといいでしょう。

Private InkeyEvent As Boolean

Private Sub 仕様書_KeyDown(KeyCode As Integer, Shift As Integer)
    If InkeyEvent Then Exit Sub 'イベント連鎖防止
    InkeyEvent = True
    If KeyCode = vbKeyReturn Or KeyCode = vbKeySeparator Then
        KeyCode = 0 'キー入力をなかっことに
        SendKeys "^~" 'Ctrl + Enter
    End If
    InkeyEvent = False
End Sub

あるいは、下記のようにイベントプロシージャの付け外ししてもいいでしょう。

Private Sub 仕様書_KeyDown(KeyCode As Integer, Shift As Integer)
    Me.仕様書.OnKeyDown = "" 'イベントプロシージャの割り当てを解除
    If KeyCode = vbKeyReturn Or KeyCode = vbKeySeparator Then
        KeyCode = 0 'キー入力をなかっことに
        SendKeys "^~" 'Ctrl + Enter
    End If
    Me.仕様書.OnKeyDown = "[イベント プロシージャ]" 'イベントプロシージャの割り当て
End Sub

ただ、こんなことをしなくても、
テキストボックスの「Enterキー入力時動作」プロパティを「フィールドに行を追加」にしておけば済みますけどね。

1
りんご 2023/06/15 (木) 20:20:36 935bc@0e907

 1つの画面に8つのリストボックスを置いて表示する感じにでしょうかね。ユーチューバー芸人を目指すならばネタとして評価されるかもしれませんが、アプリ開発言語で頑張る方が無難です。Accessに限らずお仕事にするなら大きなハンディキャップとして評価されるかもしれませんね。

2
hiroton 2023/06/15 (木) 14:40:52 4ba51@f966d

hatenaさん指摘のように詳細の見えない質問ではありますが、マクロなんか使わなくてもACCESSの基本設計で対応できる案件な気がしますね

サブフォームを含むフォーム (一対多のフォーム) を作成する

1

情報不足です。下記の情報を提示してください。

関係するテーブルの名前、フィールド構成、主キー設定を提示してください。

入力するフォームは連結フォームなのか非連結フォームなのか。連結フォームならどのテーブルと連結しているか。

入力するのはどのフィールドなのか(連結の場合)、どのようなデータなのか(非連結の場合)。

登録先のテーブル名、フィールド名。

できれば、それぞれのテーブルのデータ例を提示して、どのようなデータを入力して、どのように反映させるのか例示してもらえると的確な回答が得られやすいでしょう。

23
アクセス初心者 2023/06/14 (水) 14:04:10 fe6cd@a220e

hatenaさん
長らくありがとうございました。
無事に全ての問題を解決することができました。
ご教示いただき、誠にありがとうございました。

4
nokonoko 2023/06/14 (水) 10:59:14 3e2e6@54883

回答ありがとうございます。
テーブルに差フィールドを追加して、グラフ描画前にデータを随時更新する。
あらかじめ、クエリをオブジェクトとして作っておき、それをソースにモダングラフを作る。
こういう方針で、やってみたら少しずつ形になってきました。
今後も、なるべく用意されている機能で作っていこうと思います。

今回は、ご指導いただきありがとうございました。

3

最終目標と現在のデータから考えて、思いついたのはグラフコントロールを使ってみる方法でしたが、それが最善であるかもわかっていません。

グラフコントロールを使うなら、ソースに[差]フィールドが必要になるので、テーブルにフィールドを追加するか、クエリの演算フィールドを作成することになります。
前レコードとの差を求めるような処理はクエリは苦手なので複雑になります。テーブルにフィールドを追加できるならそちらの方がシンプルです。質問のコードを少し手直しするだけでできます。

グラフをレポートに表示させるなら、VBAですべて描画する(Lineメソッド等を使う)という方法もあります。フォームなら、直線コントロールをVBAで配置することになります。
自分はグラフを使ったこともあるのですが、結構使い方が難しく、自分の思い通りの表示にならないので、ちょっと苦手ということもあり、こちらの方法を使うかもしれません。ただ、グラフの要素をすべてコードが書く必要があるので、かなり敷居は高いと思います。なれれば自分の思い通りのグラフを作成することができます。また、描画時にVBAで差を計算すればいいので、[差]フィールドは不要です。

365なら「モダングラフ」が使えるのでこれを検討するのもいいかもしれません。私は使ったことがないのですが、使いやすそうです。(下記リンク参照)

Access2019のモダングラフの挿入(フォームやレポートで簡単グラフ作成) | Access 2019 | 初心者のためのOffice講座

まずは、上記の情報から、自身でいいと思うものを選択して取り組んでみてください。

2
nokonoko 2023/06/14 (水) 08:36:36 3e2e6@54883

テーブルに[差]というフィールドを追加することが可能なら、.edit .Update で更新することができます。

それが一番わかりやすいですね。テーブルに追加するのは永続的に捨てデータができるだけだと思って敬遠していましたが、たいしたデメリットではないので、それで対応しようと思います。

テーブルにフィールドを追加することができないなら、DLookupなどの定義域集計関数を使うか、サブクエリを使った演算フィールドを設定することになります。

今回はテーブルで対応すればいいのかなと思いますが、まだ方針が定まりません。最終的にはデータの差についての折れ線グラフ(それっぽい画像でもよい)描画が目的で、その手段が間違いであれば、根本的に考え直したいです。

また、データが空欄の場合は、差はどうなるのでしょうか。

0603のようなデータがある場合は、無視します。ロットを昇順にして並び替え、データがないものは無視し、あるものの中で直前のデータとの差を使います。

折れ線グラフはどのように作成する予定でしょうか。
グラフコントロールを利用するのでしょうか。

最終目標と現在のデータから考えて、思いついたのはグラフコントロールを使ってみる方法でしたが、それが最善であるかもわかっていません。

直線コントロールを使って自前でグラフを描画するようにすれば、差フィールドはなくても、描画するときに計算してもいいでしょう。

この考え方は全く知りませんでした。アクセスでグラフを作るのは大変だと認識しているので、この方法を検討してみたいと思います。

以上、初級者の舌足らずな説明で申し訳ございませんが、引き続きご指導のほどよろしくお願いします。

1

Null As [差] というのは演算フィールドですね。演算フィールドを更新することはできません。
この式なら Null 固定です。

テーブルに[差]というフィールドを追加することが可能なら、.edit .Update で更新することができます。

テーブルにフィールドを追加することができないなら、DLookupなどの定義域集計関数を使うか、サブクエリを使った演算フィールドを設定することになります。

どちらでご希望でしょう。

また、データが空欄の場合は、差はどうなるのでしょうか。

最終目的は、この差を使った折れ線グラフ(Rs管理図)作成です。

折れ線グラフはどのように作成する予定でしょうか。
グラフコントロールを利用するのでしょうか。

直線コントロールを使って自前でグラフを描画するようにすれば、差フィールドはなくても、描画するときに計算してもいいでしょう。

10

色々なアイデアありがとうございました(レスポンス遅くなりました)。
それぞれ試してみたのですが無反応でした。これは私が完全に理解しておらずVBAの間違い・不足によるものではと思ってます。
それで乏しい知識をひねり、対象の取引IDに対するDFirst関数で先頭のものを参照して2つ目以降を比較することで何とか上手くいきました。
もっと勉強してから頂いたアイデアも再トライしたいと思っています。
色々とお手数かけました。

6
あん 2023/06/12 (月) 10:01:04 927ea@06086

結局、VBAコードを一括変更は怖いので、1つ1つ変更していきます。
hatena様の「処理を纏める」ことを行なっていきたいと思います。

9
hiroton 2023/06/12 (月) 08:48:38 2ba59@f966d >> 7

一部修正

Private Sub 商品ID_BeforeUpdate(Cancel As Integer)
    '//最初の登録の時は何もしない
    If Me.Recordset.RecordCount <= 1 Then Exit Sub

    With Me.Recordset.Clone
        If Me!区分け <> !区分け Then
            Me.Undo
            MsgBox "区分けエラー"
        End If
        .close
    End With
End Sub

Recordset.Cloneを使うと編集前の状態でRecordsetが作成されるようです(考えてみれば当たり前)。最初のレコードの編集でも編集前と編集後を比較できるのでレコード位置のチェックは不要になりました

参考
フォームの Recordset, RecorsetClone, RecordSet.Clone の違いとは?(hatena chipsさん)

5
メイクーン 2023/06/10 (土) 21:54:45

本日教えて頂いたコードで上手く出来ました。
ありがとうございました。

1

現状、どこまでできていて、どの点でつまづているのか不明なので、とりあえず一般論として、下記のような設計になるでしょう。

データベースファイルを開いたときに、ログインフォーム的なものを表示させて、ユーザーを特定する。
ユーザーIDをどこかに保存しておく。
閲覧フォームを開くときに、そのユーザーIDでフィルターをかける。

4
hiroton 2023/06/10 (土) 08:00:56 0c5d8@2ee8f

補足
id名変数を作らなくても、端に

'// ここでできたエクセルを、名前を自動でつけて(id名でよい)、指定のパスに保存したい
  .ActiveWorkbook.SaveAs "(指定のフォルダパス)" & "\" & rs!id名

  rs.close

で、動くと思われます
変数に置くメリットとしては、rsのopen時間を減らす、ファイルの存在チェック(ファイル名の変更)ができるようになるなどです

       For j = 0 To rs.Fields.Count - 1
           If rs(j).Name = "id名" Then id名 = rs(j)
       Next j

書き出しなのでフィールドの存在チェックは不要でした

       Dim id名 As String
       id名 = rs!id名
       For j = 0 To rs.Fields.Count - 1
           .cells(1, j + 1) = rs(j).Name
       Next j
       .cells(2, 1).copyfromrecordset rs
       .Visible = True
       rs.close

'// ここでできたエクセルを、名前を自動でつけて(id名でよい)、指定のパスに保存したい
  .ActiveWorkbook.SaveAs "(指定のフォルダパス)" & "\" & id名

8
りんご 2023/06/10 (土) 02:19:06 935bc@0e907

事情がかわり取引毎に同一区分け商品だけが紐付けしなくてはいけなくなった

 取引メインテーブルに区分けフィールドを追加して下さい。
 取引メインフォームに区分けフィールド連結テキストボックスを追加して下さい。
 そして、取引明細サブフォームの商品選択(コンボにて)の抽出条件に取引メインフォームの区分けフィールド連結テキストボックスを設定するような仕組みを考えて下さい。
 例えば、ヘッダーに商品クエリのリストボックスを置く。取引メインフォーム区分け連結テキストボックスの値に応じて、動的に絞り込み、結果が表示されるようにする。必要な商品を選択して、ボタンを押せば、取引明細サブフォームの商品選択に反映されるようにする。

7
hiroton 2023/06/09 (金) 17:30:18 b43ba@f966d

もっと言えば、サブフォームのレコードソースをクエリにして、「区分け」を含むようにすれば更に簡単ですね

「取引明細テーブル」と「商品テーブル」を商品IDで結合して区分けフィールドを追加します
自分のグループで自分以外に同じ区分けがあるか?をチェックすればいいので

Not IsNull(DLookup("区分け","Q取引明細","取引ID="&[取引ID]&" AND 明細ID<>"&[明細ID]&" AND 区分け='"&[区分け]&"'"))

で、同じ「区分け」を指定していると判断できます
入力規則で判定するなら、これを使って

=IIf(DCount("*","取引明細テーブル","取引ID=" & [取引ID])<=1 Or Not IsNull(DLookup("区分け","Q取引明細","取引ID="&[取引ID]&" AND 明細ID<>"&[明細ID]&" AND 区分け='"&[区分け]&"'")),[商品ID])

VBAでやるなら、現在サブフォームに読み込まれているレコード内で比較すればいいので

Private Sub 商品ID_BeforeUpdate(Cancel As Integer)
    '//最初の登録の時は何もしない
    If Me.Recordset.RecordCount <= 1 Then Exit Sub
    
    With Me.RecordsetClone
        If Me.CurrentRecord = 1 Then .Next '//先頭レコード同士で比較しない
        If Me!区分け <> !区分け Then
            Me.Undo
            MsgBox "区分けエラー"
        End If
        .close
    End With
End Sub

このように実装できます

6
hiroton 2023/06/09 (金) 17:01:22 b43ba@f966d

VBAでやるなら更新前処理でチェックすればいいでしょう

キャンセルが理想的

入力内容はなかったことにして元に戻すならMe.Undoが使えます

Private Sub 商品ID_BeforeUpdate(Cancel As Integer)
    '//最初の登録の時は何もしない
    If Me.Recordset.RecordCount <= 1 Then Exit Sub
    
    Dim 区分け As String
    区分け = DLookup("区分け", "商品テーブル", "商品ID=" & DLookup("商品ID", "取引明細テーブル", "取引ID=" & Me!取引ID & " AND 明細ID <> " & Me!明細ID))

    If Me!商品ID.Column(2) <> 区分け Then
        Me.Undo
        MsgBox "区分けエラー"
    End If
End Sub

入力規則のように入力内容をチェックする必要はないので「区分け」の比較だけでいいですね。入力中のデータの方はコンボボックスのデータに「区分け」も含めるようにしておけば簡単に指定できます

5
あん 2023/06/09 (金) 15:30:52 927ea@06086

コメントアップ時にChr(13)とChr(10)でエラーが出たので、
Chr(13)→Chr13
Chr(10)→Chr10
としました。

4
あん 2023/06/09 (金) 15:28:43 927ea@06086
Private Sub 実行ボタン_Click()

    Dim vbcmp As VBComponent
    Dim Code As String 'モジュールのコードの文字列
    Dim CodeLine As String '置換したモジュールのコードを1行単位にした文字列
    Dim RowCount As Long 'モジュールの行数
    Dim i As Integer
    Dim j As Integer '置換モジュールの文字列の改行の開始位置
    Dim k As Integer '置換モジュールの文字列の改行の終了位置
    
    For Each vbcmp In Application.VBE.ActiveVBProject.VBComponents '全てのモジュールを1つ1つ処理
        
        Code = vbcmp.CodeModule.Lines(1, vbcmp.CodeModule.CountOfLines) 'モジュールのコードを文字列変数に代入
        
        Code = Replace(Code, Me.対象文字列, Me.置換文字列) 'モジュールのコードを置換した文字列を変数に代入
        
        RowCount = (Len(Code) - Len(Replace(Code, Chr13 & Chr10, ""))) / 2 + 1 '置換モジュールの行数
        vbcmp.CodeModule.DeleteLines 1, vbcmp.CodeModule.CountOfLines 'モジュールの全削除
        
        For i = 1 To RowCount '置換モジュールを1行1行モジュールに追加
                
            If i = 1 Then
            
                j = 0
                
            Else
                
                j = Min3(InStr(k + 1, Code, Chr13 & Chr10), InStr(k + 1, Code, Chr10), InStr(k + 1, Code, Chr13))
                
            End If
             
            k = Min3(InStr(j + 1, Code, Chr13 & Chr10), InStr(j + 1, Code, Chr10), InStr(j + 1, Code, Chr13))
            If k = 0 Then
             
                k = Len(Code) + 1
                
            End If
             
             
            CodeLine = Mid(Code, j + 1, k - j - 1)
            
            vbcmp.CodeModule.InsertLines i, CodeLine
        
        Next i
        
    Next vbcmp

End Sub

Min3に関しては、3つの数値の中で最小値が何かを算出する関数(ただし、0は除く)

Private Function Min3(a As Long, b As Long, c As Long) As Long

    If a <= b Then
    
        Min3 = a
        
        If Min3 = 0 Then
        
            Min3 = b
            
        End If
        
    Else
    
        Min3 = b
        
        If Min3 = 0 Then
        
            Min3 = a
            
        End If
        
    End If
    
    If c < Min3 And c > 0 Then
    
        Min3 = c
        
    End If

End Function

まだ、モジュール2つに対してのみ実行しただけなので、不完全でありますので、もっとテストしてみます。

ただ、hiroton様、hatena様の助言をいただきまして、実行するかよく考えなおしてみます。

3
あん 2023/06/09 (金) 15:22:39 927ea@06086

hiroton様、hatena様
ご回答ありがとうございます。

hiroton様の「コードの一括処理は余計なバグを生む」
hatena様の「纏められるものはなるべつ纏める」
勉強させていただきました。

今回、自分で試行錯誤しながら、VBAでVBAをコントロールするコードの記述ができました。

新規フォームに「実行」ボタン、「対象文字列」テキストボックス、「置換文字列」テキストボックスを配置し、
実行ボタンをクリックすると、全モジュールに対し、対象文字列を置換文字列に置き換える処理を行います。

5

hirotonさん すごく分かり易い表現でして頂きありがとうございます。お手数かけました。
中々すごい式ですね。VBAでする場合はどう記述したらいいでしょうか? サブフォームで2つ目以降の商品をコンボで選んだ時に警告が出てキャンセルが理想的です。そうすると色々と認識しやすいので。
宜しくお願いします。

2
すぬぅ 2023/06/09 (金) 13:25:12 863dd@6f7d6

はい,私もWindows10+Access2013では使うことはできていました。使っていたプログラムを,Windows11+Access2021のパソコンに移行して,壁にぶつかってしまった次第です。これも,IEのサポート終了の影響なのでしょうか・・・。
どなたか,Windows11+Access2021で使われている方はいらっしゃいませんでしょうか?

4
hiroton 2023/06/09 (金) 11:48:13 b43ba@f966d

関数は「機能をひとまとめにしたもの」なので、そこだけ抜き出せば何らかの値に置き換わります。複雑な計算式はメモ帳などで整形してみると理解しやすくなります

┌=IIf(
│ ┌DCount("*"
│ │,"取引明細テーブル"
│ │,"取引ID=" & [取引ID]
│ └)<=1
│,[商品ID]
│,┌DLookUp("商品ID"
│ │,"商品テーブル"
│ │,"区分け='" & 
│ │ ┌DLookUp("区分け"
│ │ │,"商品テーブル"
│ │ │,"商品ID=" & 
│ │ │ ┌DLookUp("商品ID"
│ │ │ │,"取引明細テーブル"
│ │ │ │,"取引ID=" & [取引ID] & " AND 明細ID <> " & [明細ID]
│ │ │ └)
│ │ └) & "' AND 商品ID=" & [商品ID]
│ └)
└)

※区分け取得部分のDLookup関数を調整

サブフォームに一番最初に区分けAの商品を選んだ場合、BやC(つまりA以外)が選べない様にしたい

これをプログラミング的な思考に置き換えていきます

本手法は入力規則を使うことにしたので、「入力可能な商品IDかどうかを判定し、入力可能であればその商品IDを入力規則の値にする」様な計算式を作成します

まず、「サブフォームに一番最初に区分けAの商品を選んだ」の時点で「最初の入力」の場合と「2回目以降の入力」で別な処理を行う必要が出ます。つまり、「何の制限もない初回入力」と「制限のかかる2回目以降」を作る必要があります

'//サブフォームのデータ単位で最初の入力と2回目以降の入力を切り分ける処理
┌=IIf(
│ ┌DCount("*"
│ │,"取引明細テーブル"
│ │,"取引ID=" & [取引ID]
│ └)<=1
│,(最初の入力)
│,(2回目以降の入力)
└)

「(最初の入力)」はどんな商品IDでも入力できる必要があるので、入力規則としては「どんな商品IDが指定されても同じ商品IDになるような式」とします。つまり自分自身を設定すれば解決です

「(2回目以降の入力)」は、「自身の区分け」と「入力済みデータの区分け」が同じかどうかを判定し、処理を分岐(そのまま入力、または、入力規則のエラーとしてメッセージ表示)させます
ただ、入力規則を使う関係上、「同じかどうか」だけでなく、「同じ場合は自身の商品ID」という結果が必要になります。そこで、DLookup関数を使って商品テーブルから「(入力済みデータの区分け)+自身の商品ID」のレコードの商品IDを求めています
これで、自身が同じ区分内の商品かチェックされるという仕組みです

'//(2回目以降の入力)部分
│,┌DLookUp("商品ID"
│ │,"商品テーブル"
│ │,"区分け='" & 
│ │ (入力済みデータの区分け)
│ │  & "' AND 商品ID=" & [商品ID]
│ └)

「(入力済みデータの区分け)」の取得方法はそのまま関数が何をやっているのか考えてみてください。


取引明細テーブルに区分けデータも記録しているのであれば、区分け判定部分の計算式はもう少し単純にできそうですね


実装方法はいくつか考えられますが、「入力規則に計算式を一つ入れればいい」が謳い文句として簡単そうに見えたのでそれで実現しています。(VBA使ったほうがすっきりする回答になるんですけどね)

1
hiroton 2023/06/09 (金) 10:23:32 b43ba@f966d

ネット検索する限りIEはなくてもWebBrowserコントロールはそのまま動くように見えますね
こちら、Windows10ですがファイルは読み込めました

ひとつひとつ問題の切り分けをして試してみてはどうでしょう?

3

構成は下記です。
1.ユーザーテーブル:●ユーザーID(主キー) ●ユーザー名
2.商品テーブル:●商品ID(主キー) ●商品名 ●区分け
3.取引メインテーブル:●取引ID(主キー) ●日付 ●ユーザー選択(コンボにて)
4.取引明細テーブル(サブ):●明細ID(主キー) ●商品選択(コンボにて) 他数量等 ●取引ID
この3と4を使い(取引IDを1対多でリレーション)して親子フォームを作成しています。
フォームのページというのは私が勝手に認識してました。取引ID毎の親子フォームになっているもので。
取引入力時にその時のサブフォームで一番最初に選択した商品区分け以外の区分けを選ぼうとした場合に警告を出しキャンセルさせたいのです。少し前からこのフォームで処理していたのですが事情がかわり取引毎に同一区分け商品だけが紐付けしなくてはいけなくなったので(過去に入力されたものはいいのですが、今後で)

hiroton さん早速ありがとうございます。関数単体の意味はわかるのですが全体の処理はどういう動きでしょうか?(長い関数式が慣れてなくて、すみません)

宜しくお願いします。

2
hiroton 2023/06/09 (金) 09:32:37 b43ba@f966d

何をもって簡単と言うかわかりませんが
コンボボックスの入力規則に以下を設定します

=IIf(DCount("*","サブテーブル","リンクフィールド=" & [リンクフィールド])<=1,[商品],DLookUp("商品","商品テーブル","区分け='" & DLookUp("区分け","商品テーブル","商品=" & DLookUp("商品","サブテーブル","リンクフィールド=" & [リンクフィールド])) & "' AND 商品=" & [商品]))

※各項目は実際のフォームの内容に合わせる必要があります

1
りんご 2023/06/09 (金) 07:56:00 935bc@0e907

リレーションシップも定義済みです。
スクリーンショットを提示できますか?難しければ、主キーとリレーションシップを書いた方が、回答が増えるでしょう。
他に確認すべきところありますでしょうか。
タブを使わずに、メインフォームとサブフォームで該当部分を試しに組んでみるとか?

2

同じようなコードの置換、追加が多数必要になるということは、同じような処理が多数あるということですよね。

Private Sub PI担当者ID_AfterUpdate()

ということから推測すると、多数のコントロール(テキストボックス等)があり、そのコントロールで更新が発生したら、PI測定日を現在の日付を入力してメッセージボックスを表示させたい、
ということがご希望のことかと思えますがどうでしょうか。

こういう場合、共通の処理は一つのプロシージャにまとめておくと修正があっても一か所ですみます。

例えば下記のようなに。

Sub Ctrl_Update()
    If Isnull(Me.ActiveControl) = False Then
        Me.PI測定日 = Date
        Msgbox "日付を代入しました。", vbokonly '追加
    End If
End Sub

Private Sub PI担当者ID_AfterUpdate()
     Ctrl_Update
End Sub

Private Sub 他のコントロール_AfterUpdate()
     Ctrl_Update
End Sub

さらに共通処理の部分をFunctionにしておけば、

Function Ctrl_Update()
    If Isnull(Me.ActiveControl) = False Then
        Me.PI測定日 = Date
        Msgbox "日付を代入しました。", vbokonly '追加
    End If
End Function

デザインビューでこの処理を適用したいコントロールを複数選択しておいて「更新後処理」に

=Ctrl_Update()

とすれば、コントロール_AfterUpdate() のコードをコントロール数分記述する必要もなくなります。

同じような処理を複数個所に繰り返し記述するはバグの原因になりかねませんので、纏められるものはなるべつ纏めるというのがプログラミングの鉄則で。

1
hiroton 2023/06/08 (木) 17:11:35 dd05a@f966d

標準のエディタには無い機能なので、それができるエディタを使うとか、[F3][END][CTRL+v]を繰り返すとか、それをマクロで作るとか

あとは改行の代わりに:を使ってマルチステートメント記述にするとか

まぁ、コードの一括処理は余計なバグを生むこともありオススメしませんが

3
nokonoko 2023/06/08 (木) 17:02:54 3e2e6@54883

今回はありがとうございました。
予定通りの作業ができるようになりました。

1

メインフォームのレコードソースはテーブルはユーザー情報を格納するもの。
サブフォームのレコードソースはそのユーザーが購入する商品データを入力するもの。
ということですか。

できれば、関係するテーブルのテーブル名とそのフィールド構成を提示してもらえますか。
少なくとも下記の3つのテーブルが必要なはずです。
ユーザー情報のテーブル
商品購入データのテーブル
商品情報のテーブル

データーベースはまずは、テーブル設計が重要でそれがまちがっていたら、使い物にならないので。

。フォームのページ毎に一つの商品区分け分商品しか選択出来ない様にしたいのです。

フォームにページという概念はないのですが、どのような意味が使っていますか。

2
nokonoko 2023/06/08 (木) 13:45:03 3e2e6@54883

回答ありがとうございます。
やりたいことができるようになりました。
しかし、このあたりのコードをまだいじっている途中なので、またこの続きに質問することがあるかもしれません。その時は、お時間がありましたら、よろしくお願いします

コードミスを見落としてました
openに対してcloseがないですね

ご指摘ありがとうございます。エラートラップのほうにまぎれて入っていました。