Accessでは削除したレコードは基本的には復活できません。削除する前に確認するようにしても、つい、うっかりと削除してしまう場合や、必要ないと思い削除しても後で必要になる場合もあったりします。 OS のごみ箱のように、いったんごみ箱へ移動しておいて、必要になったらまた復活させることができると便利ですね。テーブル単体では無理ですが、フォームから入力、削除するようにすれば、比較的簡単に実現できます。 ...
Dim rsA As Recordset, rsB As Recordset, rsMe As Recordset
Set rsMe = Me.Recordset.Clone
Set rsA = CurrentDb.OpenRecordset("T_A")
Set rsB = CurrentDb.OpenRecordset("T_B")
Do Until rsMe.EOF
If Me!テキストボックス = "なんかやる" Then
Do Until rsA.EOF
Do Until rsB.EOF
If rsA.f1 = rsB.f1 Then
'//なにかする
Exit Do
End If
rsB.MoveNext
Loop
'//なにかする
rsA.MoveNext
Loop
End If
rsMe.MoveNext
Loop
rsA.Close
rsB.Close
rsMe.Close
情報ありがとうございます。先方は以前のシステム管理者で現在はいないかたのようです。
現在は私がaccessの編集などをしております。
結論はOffice32bitをインストールを行うしか動作環境は作れないということで間違いないでしょうか?
runtimeは作成したときのビット数と同じでないと動作しないという仕様のようです。
https://zawazawa.jp/ms-access/topic/628 でもhirotonさんがリンクを紹介してますね。
ACCDEファイルが32Bit版と64Bit版で共有できない : Access
Office 32bit環境を用意するか、先方に64bitで作成しなおしてもらうことになるかと。
質問のリンク先
論理削除はアンチパターンなのか? #MySQL - Qiita
で提示されているデメリットについて今回の案件で検討してみます。
パフォーマンスへの影響
現在レコード数が約5万件、月2~300件程度の追加、削除(キャンセル)件数3%程度
このぐらいのデータ件数なら、削除フラグフィールドにイデックスを設定しておけば、ほとんど影響ないとかんがえていいと思います。
クエリの複雑化
Accessではクエリはテーブルと同等に扱えます。
上記の回答でしたように、論理削除レコードを除いたクエリを作成しておいて、それを使えば、現象のクエリやフォーム、レポートの修正する必要はありません。
クエリも複雑化しません。
ユニーク制約に工夫が必要
リンク先ではusersテーブルのメールアドレスにユニーク制約(Accessでは「重複なしのインデックス」)を設定する場合を例に挙げてますが、おそらく今回の注文テーブルではそのようなフィールドはないのではないかと。
あったとしても、私の回答の方法では削除日時をフラグフィールドにしているので、複数フィールドインデックスでユニーク制約の設定は可能です。
ということで、今回の要件なら大きなデメリットはないかと思います。
会社のパソコンからは、他サイトに書き込み出来ない為、スマホの画像をコピーして貼り付けてみます。当方は、デスクワークは、殆どしていません。ですのでお時間を頂く事になります。宜しくお願い致します。
SQLはSQLビューで全選択してコピーして、貼り付けてください。
貼り付ける場合は、Markdown記法のコードブロックにしてください。
やり方は下記で説明していますので参照してください。
Microsoft Access 掲示板 の使い方 Microsoft Access 掲示板 - zawazawa
あと、レポートのデザインビューのスクリーンショットを「画像アップロード」してください。
ご返答ありがとうございます。クエリのSQLは、SQLビューをスマホで写真撮った物をアップしても良いですか?
「まずありません」ということは「絶対ない」ではない「わずかであるがありうる可能性がある」ということですよね。
Accessデータベースはファイルサイズ2GBの制限がありますが、それに達する可能性がないのなら、私なら削除せずに「削除フラグ」を立てておくという方法をとりますね。
インデックスを適切に設定されているなら、パフォーマンスにほとんど影響はないと思いますので。
OSに実装されている「ごみ箱」の機能と同等のもの実装するということをしたことがあります。下記でサンプルを紹介していますのでご参考に。
上記のサンプルでは削除日時フィールドを追加して、それがNullのレコードは生きているレコードと、日時が入力されいいるレコードは削除レコードとしています。
こうしておけば、例えば削除後X年経過したら自動的にテーブルから削除するとか、削除してもいいか確認するとか、、、運用に合わせてお好みに設計できます。
レポートのレコードソースのクエリのSQLを提示してもらえますか。
あと、レポート上のSum関数が設定してあるコントロールのコントロールソースに設定してある式、そのコントロールが設定してあるセクション名、レポートのグループ化/集計の設定も提示してもらえますか。
商品マスタの商品コード999(メインフォーム)と見積の商品コード999(サブフォーム)を親リンク子リンクすれば、>> 7に近い形になると思いますが、それじゃダメかしら?もしダメならば、どうしたいのかを簡易図(例、スクショ)と文章で説明していただけますか?
ご回答有難う御座います。1の例で行くと選択クエリに合計数を求めているフィールドが2つあり、その両方が空欄の時が総合計が空欄になります。両方とも空欄になる場合どういう風に抽出条件を書けば良いですか?is nullでも非表示できますが、
フィールドの構成を変えない場合の記述の仕方がわかりません。ご教授頂けますと幸いです。
「既存のデータベースであり、キャンセルのフラグがある」なら、キャンセルを抽出条件に使います。すでに運用中であり、仕様を完全に把握しているのでなければ、データの削除に対する影響がわかりません
「既存のデータベースであり、キャンセルのフラグがない」なら、集計に含まないとする条件をそれぞれ追加するしかないでしょう
「既存のデータベースであり、キャンセルを削除する」を考えた場合、今後の運用に問題はないでしょうか?それを正しく削除できますか?誰が、いつ、できますか?
hirotonの場合、設計段階として、Nullを数えるような仕組みを極力排除します。仕組みとしては、「現物票出力日」「出庫日」「梱包明細出力日」の他に「状態」フィールドを設け、「
-1;キャンセル;0;現物票未出力;1;未梱包;2;未出庫;3;出庫済み
」とします。明確に目的のものを集計するのでミスが起こりませんキャンセルについては、「梱包まで済んでキャンセルになった」のようなそれをどうするんだ?という場合もあると思います。要求に合わせて「受注状態(キャンセル・受注・納品済み)」「作業行程(伝票未発行、未梱包、未出庫、出庫済み)」のように、複数フィールドで管理する場合もあります
-1からの連番にしてしまっているので設計段階で工程をしっかり把握しておく必要があることには注意が必要です。「状態マスタ」テーブルを作成して、数値に意味を持たせないのが正しい正規化ですが、末端の情報にそこまで神経質になって後から良かったと感じたことはそれほどないです
当たり前ですが、削除すべきデータは削除します(ミス登録とか)
「キャンセル」というアクションは「存在しなかったもの」として扱っていいモノでしょうか?そうであるならば、「キャンセル」というアクションが起きたときにデータを削除するようにすればいいです
「とりあえず削除フラグ」というやり方は削除フラグが問題の原因ではなく、「とりあえず」という妥協する姿勢が問題になるのです
およそ3%が問題のデータということですが、パフォーマンスが問題になった場合、不要分のデータが存在しなかったとするならば、問題が発生するまでの期間の3%の期間だけ延命できることになります
パフォーマンスが問題になるならば、もっと根本的な解決が必要です
りんご様
回答ありがとうございます。
ご指摘のとおり同等品商品コード1〜5いずれかに商品コードが対応した場合にサブフォームに表示されるようにしたいと考えております。
お手数ですがよろしくお願いいたします。
下記の2つの方法が考えられます。
>> 6
SQLのようなコードではなく、商品コードの事だったんですね。理解不足でしたね、すみません。
>> 5
例、見積テーブル
商品マスタの商品コード:999
見積の同等品商品コード1〜4:001,002,003,004,005
やりたい事は、見積テーブルの商品コードを開いたら、対応する同等品商品コード1〜5がサブフォームに表示される、みたいな感じかしら?
りんご様
ご指導ありがとうございます。
hatena様がおっしゃる通り初心者であまりわかっていません。これから少しずつではありますが勉強させていただきます。
またご助言をいただければ幸いです。
hatena様
回答が遅くなり申し訳ありません。
また、説明不足もあり大変失礼いたしました。
今回の件を再度ご説明させていただきます。
今回の件は、商品の見積もりのデータベース化を目的としています。メインフォームにて商品を表示させたときにサブフォームに同一商品見積一覧、もう一つのサブフォームに同等品見積一覧を表示させようとしています。
テーブルは商品マスタと見積の2つになります。
商品マスタのフィールドには、日付(日付/時刻型)、品目(短いテキスト)、メーカー(短いテキスト)、商品名(短いテキスト)、商品コード(短いテキスト)があります。
見積のフィールドには、日付(日付/時刻型)、商品コード(短いテキスト)、同等品商品コード1(短いテキスト)、同等品商品コード2(短いテキスト)、同等品商品コード3(短いテキスト)、同等品商品コード4(短いテキスト)、同等品商品コード5(短いテキスト)、価格(通貨型)があります。
なお、商品マスタの商品コードと見積の商品コードをリレーションシップしてあります。
メインフォームはフォームデザインにて商品マスタのフィールドと商品見積一覧のサブフォーム、同等品見積一覧のサブフォームを表示させてあります。
メインフォームのレコードソースはテーブルの商品マスタになります。
商品見積一覧のサブフォームのソースオブジェクトはテーブルの見積でリンク親フィールドならびにリンク子フィールドは商品コードにしてあります。
同等品見積一覧のサブフォームのソースオブジェクトはテーブルの見積でリンク親フィールドは商品コード;商品コード;商品コード;商品コード;商品コード、リンク子フィールドには、同等品商品コード1;同等品商品コード2;同等品商品コード3;同等品商品コード4;同等品商品コード5にしてありましたが同等品は表示されませんでした。
拙い説明ではありますが以上になります。また、不足している場合があるようでしたらご面倒をおかけしますがご指摘をよろしくお願いいたします。
hatenaさんの仰る通りの状況です。もし、レポートを弄れるとしたらどうすれば良いでしょうか?
SUM関数の集計がレポートのレコードソースのクエリにあるのなら望みはありますが、
レポート内のテキストボックスで=Sum([フィールド名])などとしている場合は、
レポートを一切触る権利が一切ないなら無理ですね。
DoCmd.OpenReport の引数のフィルターに合計が文字列0を指定すれば出来るのか試してみます。ありがとうございました。
レポートを一切触る権利が当方には有りません。当方が、作ったレポートでは無い為でかつ長年そのフォーマットで運用してきた為です。空欄が出るのは、お客様が休業日で注文が無かった場合発生し、レポートにある総数量を求めるSUM関数が0の時空欄になります。ですので、受注次第で総数量が0の時は変動し、無駄紙となります。帳票の構造は、テーブルに注文のあったメーカーの注文数をフォームを通してテーブルに入力していく構造です。総数量の合計0を取得できればよいのですが。毎日の印刷枚数は、200前後で平日は、無駄紙が余り発生しないのですが、連休が絡むと細々と発生します。
現状、手作業で無駄紙を破棄しているのなら、
手作業にはなりますが、プレビューで無駄紙のページ数を確認して、印刷するときに無駄紙を除いたページを指定して印刷すれば、用紙の無駄遣いは抑制できますね。
レポートにいっさい手を付けることができないという状況でしょうか。
私が提案したレポートのイベントを利用することも含めて。
そもそもなぜ、空欄のページで出るのか、その仕組みが不明です。データがないものは出力されないのが通常ですので、なんらかの特別の方法をつかっていると思うのですが、どのような方法を使っているのか提示できませんか。
レポートのレコードソースのクエリにも手を付けられないのでしょうか。
抽出条件を設定することで、空欄の出力を抑制できるのなら、
DoCmd.OpenReport の引数にフィルターを設定できるので、それを利用できるかもしれません。
あるいは、空欄になるページが事前に取得できるなら、DoCmd.PrintOut で印刷するページ数を指定できるので、空欄以外のページを印刷するようにはできます。
どちらにしても、提供されている情報からは、これ以上の具体的な提案は難しいですね。
ご返答誠に有難う御座います。無駄紙は、いつも廃棄しており、経費節減の為何とかならないかと考えていました。総数量の座標が空欄の時をvbaやCOM等で取得しvbaで具現化できればと考えていました。vbaは、accessから独立しておりクエリ等を弄るのでは無く違った方法で出来るのではと考えておりましたが、もし可能であっても相当難しそうですね。
hirotonさんの回答でほとんど網羅してますが、少し補足を。
標準モジュールから、プレビューされたものを制御することはできないでしょう。
イベントをハンドルすることが可能なら、レポートの「フォーマット時」イベントで
Cancel = True とすれば、そのセクションの出力をキャンセルできますので、それを使うことができるかもしれません。
要件が不明瞭ですね
何がよくて何がダメなのかわかりません
お客様の要望で無駄紙なのでなくしてもいい・なくしたいなのでしょうか?
すべて空白でも必要な書類というものもあるので、ここまでの話では、手を入れてはダメなのでは?と思います
普通、出力不要なモノはレコード単位で出力を制限します(データベースなので)
これを制御するならクエリです(または、そもそも数量のないものはテーブルに記録されないので出力されません)
レポートの書式を一定に保つならば
余白に応じて行数指定無く用紙の最後まで罫線を出力する(hatena chipsさん)
書式を一定に保つ手法はアプローチがいくつかあるので使いやすいものを検討すると良いです
これは「レポート」を変更(改修)することになります
上述した通り、そもそも存在しないものが出力されている状態が疑問です。何かそうしなければならない理由とそれを実現するために構築したレポートの仕様があるはずです
特殊な事情があるのであれば状況や仕様の説明がなければ解決案も出せません
各ページに出力される項目が固定ならば、事前にその項目のグループで集計を行って、出力のあるグループだけをクエリで抽出すれば実現できると思います
ACCESSはデータベース管理ソフトです。データを効率的に管理、運用するために、テーブル、クエリ、フォーム、レポートを相互に連携させながら適切なデータ構造の構築、操作の制限、処理の最適化を行っていきます。これらを「変更できない」では何もできません。「ACCESS」がどのようなアプリケーションなのか、正しい理解と、お客様とのすり合わせを行って、何をしたいのか、何故それがダメなのか、本当にそれが望んでいることなのか見極めてください
あー確かに。すごくわかるんですけど、経験不足などでこの回答は難しいです。
hatenaさん、hirotonさん、skさん・・・だったかな、もっと詳しい回答者の方々、お願い♪
ご返答有難う御座います。レポートは、空欄ありきになっています。そのレポートは、お客様の要望の構成になっており、いじる事が出来ません。総数量欄が空欄のページの取得が出来るだけでも助かるのですが、難しいでしょうか?
レポートが元々空欄マスありきになっていて、問題が発生している場合、そうならないように新しいレポートを作成するのはどうでしょう?
レポートのレコードソースに元々不要なものが含まれていて、問題が発生している場合、レコードソースを遡って、フォーム・クエリ・テーブルを改善するかな。
ご返答有難う御座います。テキストファイルにvbaのコードを貼り付けて、標準モジュールに貼り付けて実行を考えていましたが、特殊なイベントをハンドルする必要がある場合は、許可を貰えば可能です。変更が難しいのは、レポートを構成する要素でテーブル、クエリ、レポートは、難しいです。
因みに、この様な無駄紙を発生させたくない場合、一般的には、どの様な手法を取るのでしょうか?
印刷プレビューを呼び出す前後で直接外すのは難しいでしょう。
変更を加える事が出来ないようになっているのであれば、例え可能であったとしてもレポートに変更を加えるVBAは控えたほうがよろしいのではないかしら?
不明な点は推測で補って、下記のようだと仮定すると、
サブフォームのレコードソースは「コードをいれるフィールドが5つあるテーブル」
テーブル名 Tbl1
5つのフィールド名 Code1, Code2, Code3, Code4, Code5
メインフォームにコードを入力するテキストボックスが一つある。
メインフォーム名 MF1
テキストボックス名 txt1
このテキストボックスのコードがCode1~Code5のいずれかと一致しするレコードを抽出する。
だとしたら、
Tbl1からクエリを作成して、デザインビューで下記のように設定
今回の条件はOR条件ですので、抽出条件は上記のように行をかえて設定します。
ちなみに、親リンクと子リンクの設定ではAND条件になりますので、今回の要件では使えません。
このクエリをサブフォームのレコードソースにする。
txtコードにコードを入力したら、サブフォームを再クエリする。
上記の前提では、テーブルの正規化ができいません。
場合によっては、テーブル設計から見直すべき事案かも知れません。
テーブル情報などの詳細が現時点では不明なので、その辺がはきっりしてから、アドバイスします。
りんごさん
質問者さんは初心者といわれています。
初心者にそのような回答をしても、もはや意味不明の回答だと思います。
ブロックプログラミングみたいな事をやりたいのであれば、詳しくないけれど、kintoneやwagbyあたりを調べてみるのはどうかしら。Excelで楽曲作成演奏をやろうとするなら、初音ミクみたいなものを提案しますよね?
ところで、MsAccessを選んだ時点で当たり前のルール(主キー、正規化)を受け入れなければいけません。例えば、運動場でサッカーやろうぜ、でも、足技禁止・手技のみOKルールな!サッカーボール以外もなんでもOKな!、みたいに、何でもありを許したら、それはもはや意味不明な質問です。
追記:コードとは、プログラムコードじゃなくて、商品コードのようなものだったのかしら?
表現があいないなので、正確な状況が把握できません。
サブフォームのレコードソースのテーブルに「コードをいれるフィールドが5つ」あるということでしょうか。
「5つのフィールドいずれかのコードと合致した場合」の合致する値は、メインフォームのテキストボックスに入力するということでしょうか。
メインフォームは連結フォームでしょうか。値を入力するテキストボックスは連結コントロールでしょうか。
もう少し情報を整理して、正確かつ詳細に説明していただけませんか。
下記のような情報は欲しいです。
テーブル名
フィールド名(データ型)
データ例
メインフォームのレコードソース
サブフォームのレコードソース
デザインビューで枠調整をしたのですが上手くいかず、MoveSizeメソッドでやってみたところ期待通りのフォームサイズになりました。
皆さま、ありがとうございました。
DoCmd.MoveSize メソッド (Access)
そのフォームを読み込んだ時にサイズを変更したら良いかな
hirotonさん・skさんもありがとうございます。実際使って試しなががら勉強していく様にします。それにしても奥が深いものですね。でも上手く出来た時は感激しますので頑張っていきます。
色々とありがとうございました。
あとこれも。
オブジェクト変数の作成
変数宣言が必要なのは同一のオブジェクトを操作する必要があるとき、ですかね
間違った実装
hatenaさんも解説されていますが、
With
ステートメントを使うとこんな時でも変数宣言をしなくてもよくなります複雑になってくると、どのオブジェクトをWithステートメントで省略したらいいか悩みどころで、省略しないほうが見やすいコードという場合もあります
コードが長くなってくると、
//なにかする
のところでWith
で省略した記述がrsMe
なのか、rsA
なのか・・・と本人でも混乱するようになってくるので見やすさ重視で変数を使うなんてこともよくありますApplication.CurrentDb メソッド (Access)
Access の CurrentDB はキャッシュしよう(IT raises ITさん)
CurrentDb
についても、本来はとしたり、または
With
ステートメントで参照して使用したほうが正しい使い方ができます。上記のような、クエリを複数回実行するのような場合を考えると、実は「CurrentDb.Execute
」を繰り返すとは少し違う動作をしますまぁ、よほどのことがない限り、ただクエリを実行するだけであれば
CurrentDb.Execute
の1行だけで済ませられるメリットを優先で問題ないので、それで回答している感じですねDBEngine.OpenDatabase メソッドまたは Workspace.OpenDatabase メソッドを使用する場合。
DAO.TableDef オブジェクト型の変数を使用して任意のテーブル定義を参照する場合。
DAO.Recordset オブジェクトの Filter プロパティや Sort プロパティを使用する場合。
Access とは別の Office アプリケーション( Excel や Word などの)の VBA プロジェクトにおいて DAO を使用する場合。