Access VBA 質問スレ Part2
Access の VBA に関する質問スレです 質問テンプレ(雛形)は用意しませんが、OSとAccessのバージョンぐらいは必ず書きましょう 前回のスレッド Access VBA 質問スレ Part1 https://mevius.5ch.net/test/read.cgi/tech/1328536426/ ただでさえポンコツな言語なんだから、クラスぐらい使おうよ。 >>673 そのせいだったのか、クラス使えば良かった ADOでCSVからテーブルを作ろうとしたらレコードが大きすぎますって怒られるんですよ! 1レコード2000バイトも無いのにですよ! 400列くらいあるのがダメなんですか? 2013なんですが。 過去最大のフィールド数は500 テーブル分割して収納した Access2019でリボン非表示にするのは、どうするの? XML??? VBAでなら DoCmd.ShowToolbar "Ribbon", acToolbarNo ってのがあるが それだと使用者に解除されちゃうので、XMLで空のカスタムリボン作って、オプション→現在のデータベース→リボンとツールバーのオプションに設定したいんよ Access2019だとスクラッチからリボン作ってもファイルボタンが残っちゃうのが解ったので、それで我慢する サブフォームをもつフォームにおいて、 親フォーム側から Me.サブフォーム.Requery を実行すると、サブフォームのCurrentイベントが2回発生するんだけど、なんでなんだろ? 大抵はそう組まれているからそう動作する 親フォームからひとつずつチェックしてみれば「あぁ、ここか」が出てきたりする >>688 検証のために、メインフォーム上ににサブフォームとサブフォームをRequeryさせるだけのボタンの最小限の構成にしても 687で書いた現象が発生している(サブフォーム側はCurrentイベントにdebug.printを書いただけ) 私は何か根本的な勘違いをしているのだろうか?それともAccessの仕様なのだろうか? フォームをデザインビューにした時に出て来るプロパティシート おおむかし、あの枠が狭くて知らぬ間に二行に記載していたことは稀によくあった Excelで言う、セル内改行をやってしまっていた 見た目はいっこなので気付きにくい 或いは、サブフォームをよりシンプルなものでテストするとか 仕様なら同様の質問疑問がてんこ盛りに投稿されるはず と思って探ってみたら、こんなのが・・ http://yamav102.cocolog-nifty.com/blog/2015/05/from_current-96.html これ系? >>690 サブフォームは新規作成した状態のものにCurrentイベントにdebug.print書いただけのものでも2回発生してるのよ 提示していただいたページはこちらで調べたときに見ていますが、そのページで書かれてるのは自分自身に対するRequeryのようなのでちょっと事情が違うようです frmMain ------------------ Option Compare Database Option Explicit Private Sub btnRequery_Click() Debug.Print "clicked ------" Me.frmSub.Requery Debug.Print "--------------" End Sub -------------------- frmSub -------------------- Option Compare Database Option Explicit Private Sub Form_Current() Debug.Print "frmSub Form_Current" End Sub --------------------- こんなかんじの検証用のを用意 んで、実行結果(イミディエイトウィンドウ)が clicked ------ frmSub Form_Current frmSub Form_Current -------------- イメージだけで応答してたから、どうにもとっ散らかってた 現物当たって真似してみた https://learn.microsoft.com/ja-jp/office/vba/api/access.form.current このイベントは、フォームが開いたときと、フォーカスがレコード間を移動したときの いずれの場合にも発生します。 複数回発生して当たり前だった Form_Load (読み込み時) 或いは Form_Abtivate (アクティブ時) に変えればおk どうしてもForm_Current (レコード移動時)に設定したい場合は見て見ぬ振りをするしか >>693 loadやactivateではrequery時にイベントが発生しないので、本来の目的を達成できません また、最初にフォームが開かれたときにはcurrentは一度しか発生していません btnRequery をクリックしても Requery できない?という意味? Me.frmSub.Requery を Me!frmSub.Form.Requery にしてみては? Me. か Me! かでも変わって来るし、.Form を付ける付けないでも挙動が変わったような あと、frmMain を開いただけでも frmSub Form_Current が発生するのも違う気がするし frmMain でパラメータ変えて frmSub を Requery させたいとかなら https://teratail.com/questions/123328 このhatenaさんの回答を参考にしてみたり Docmd.Requery でやっつけてみたり Requeryの使い方もクセがあるので切磋琢磨が 必要だったり >>695 frmSubはfrmMainに貼り付けられているのでfrmMainを開くと当然frmSubも開かれるので、 Open, Load, Current等のイベントはひととおり発生します(仕様通り) これについては特に問題ではありません 問題にしているのはbtnRequeryをクリックしたときに、Me.frmSub.Requeryを一度しか呼んでいないのに frmSubのCurrentイベントが二度発生していることです 紹介いただいたteratailのページを参考にあれこれ試してみたいと思います AccessにGROUP_CONCATみたいなのなかった? サブフォームのレコードソースにテーブル指定して >>691 やってもカレントは一回しか表示されんけどな レコードソース無ければ2回カレントは表示される サブフォームにレコードソース指定してる? >>698 たしかにレコードソースはしていしていません なるほど理由はよく分からないけれど、原因は分りました ありがとうございます ちょっと不思議な話 よくある数値の切捨て処理のfunctionとして Function RoundDownDec(decNum as Currency, intPlace as Integer) as Currency RoundDownDec = Fix(decNum * 10 ^ intPlace) / 10 ^ intPlace End Function 処理したいデータの都合で与える数値も戻り値も十進型としています (正負の処理などは今回の本題から外れるので例からは省いています) RoundDownDec(33.6, 2) としたときに、33.6が返ってくるのを期待しますが33.59が返ってきます 不思議! functionの中身を Dim tmp As Currency tmp = Fix(decNum * 10 ^ intPlace) Debug.Print tmp RoundDownDec = tmp / 10 ^ intPlace と段階を踏ませるとイミディエイトウィンドウに3359が出るので更に tmp = decNum * 10 ^ intPlace tmp = Fix(tmp) と分解すると、期待通りの結果(33.6)が得られます Fix()の引数はdoubleなんで、暗黙的な型変換が行われているせいなんだろうけれど、微妙に納得がいかない不思議な話でした ちなみに蛇足ですが、普通に Function RoundDown(dblNum As Double, intPlace As Integer) As Double とdoubleを引数にした場合は、特別なことをしなくても RoundDown(33.6, 2) の結果は33.6となります 浮動小数点を経由するので誤差から免れることはできません(以下はイミディエイト ウィンドウでの実行と結果) ? Fix(33.6 * 10 ^ 2), Fix(33.6@ * 10 ^ 2), Fix(33.6! * 10 ^ 2) 3360 3359 3359 単精度でも同様 ? Fix(33.6@ * 10 ^ 2) / 100, Fix(CCur(33.6@ * 10 ^ 2)) / 100, Fix(33.6@ * 100) / 100 33.59 33.6 33.6 べき乗を使うことが誤差を生む原因の一部でもあったりするので、CCur()で一度補正?したりで影響を減らすとかも考えられます。 検証ありがとうございます 浮動小数点を経由するので誤差がでるのは理屈としては理解できるのですが、 わざわざ十進型を使ってるのに…というのや、Fix()に渡される式の結果ではなく、 渡された段階で暗黙的な型変換が行われているっぽいのが腑に落ちなさの一因なのでしょう ? Fix(33.6@ * 10 ^ 2) , Fix(33.6@ * 100) 3359 3360 の結果からもわかるように、今回の場合は 10 ^ 2 の値が浮動小数点であり ≠100 である ということです なので「33.6@ * 浮動小数点」は33.6@を浮動小数点として計算する(はず)ので、その結果が 許容できない値になってしまったと 対策として CCur(33.6@ * 10 ^ 2)で本来の値に近くなるように書きましたが、 べき乗の部分を一度整数変数に代入してから「33.6@ * 整数変数」の形にしてもいいと思います(未検証) この場合、通貨型は内部整数 * 整数なのでここまでの計算結果に誤差はでません。(乗数マイナスは別) RoundDownDec()を大量に使用する場合はパフォーマンスも考慮しないといけませんが、乗数を整数変数経由に する方が CCur()関数使うより早いのではと思います(昔、関数使うと遅いなと思った経験)。 100万回くらい(適当)ループして検証してみてください。 更なる解説ありがとうございます ? TypeName(10^2) Double 正直これは盲点でした 原因がはっきりわかりすっきりしました ありがとうございます VBAの内部計算につかう型は結構複雑な変換をする 33.6@ * 整数変数の結果は、Currency型だぜ 多くの関数や演算子で、より精度の高い型を使おうとするんだが、べき乗はDoubleしか返さん仕様っぽいな 自分でCurrencyかDecimalでべき乗する関数作れば解決 OpenArgsってなんて読んでますか? 何の単語の略なんでしょうか ご存じのかた教えてください >>706 CurrencyかDecimalでべき乗する関数ってどのような? >>708 こまかい条件省くとこんな感じじゃね Function pow(x As Currency, y As Integer) As Variant Dim i As Integer Dim ret As Variant ret = CDec(x) For i = 1 To y - 1 ret = ret * CDec(x) Next pow = ret End Function Decimalは直接定義できないからVariantで宣言してる >>707 おーぷんあーぎゅめんつ argsはargumentsの略 引数 >>709 そんな低レベルな関数書いて「解決っ」とか言っちゃって時点でバカにも程がある 業務用のmdbがポンコツコードだらけなので書き換えてるんだけど、IIFが最大4個ネストしてあった。 4個ネストしてあるのは変数の値の判定が条件になっているけど、3個以下のは関数を呼び出している。 皆さんだったらどうします? 将来も含めてどのレベルの人がメンテしていくかだろうな ソースの書き方も人それぞれ 例えばコメントの書き方でも、巷では行間に書くのが多いが、私は画面内に一度に表示できるロジックの行数減って見通し悪くなるから、行末側に書きたい 画面も横長だし とか厳密に書き方決めないと人それぞれになってしまうのよね ネストの段数にしても固定してしまうと、ムダに外出ししてしまうとかもあったり ソースを見やすくするか、コメントで逃げるとかはもうコーティング規則にするか、それしないなら担当者判断でしかない iifもネストなんて場合によりどちらでもいい とりあえず、測定用の簡単なVBAを作って、IIFのネストがどのくらい遅いのか確かめてみます。 変数の値の判定くらいなら差はほとんどないという記事を読んだことがあります。しかし、関数呼び出しをするとかなり違うという記事も読んだことがあります。 なので、呼び出された関数が10個、さらにそれぞれの関数が10個の関数を呼び出すようなコードでも書いて調べてみます。 昔Ken Getzの本を何冊か読んだ記憶ではOptimizationの章では揃ってIIfを避けるように書いてありましたね。 >>714 あぁ、それなら全ての条件を評価する(初期の判定で達しないとこも)から、遅くはなる そういう弊害があるから一律使わなくするなんてことは、あったりするだろうね そういうの見ると「はぁ⤵」って思うけど >>715 ちなみにif~thenも全判定なので、iif禁止で問題解決になるわけでもない >>714 Access のIIFの問題は判定結果に関わらず TrueパートとFalseパートの両方が評価(関数なら実行)されてしまう仕様 a = IIF(True, funcA, funcB) funcAだけでなくfuncBもコールされる aにはfuncAの戻り値が入る 関数の実装内容によってはパフォーマンスに影響が出るでしょうね IFではどちらか一方のみ結果パートが評価されます >>716 if thenが全判定てなにを言っているんだ andとorがショートサーキット演算しないだけだぞ 基本vbaはショートサーキットしない 例外はif関数ぐらいか >>718 日本語理解できない、省略を補完する知識もないシナのアホが飛来したな Select CaseはTrueが出たところで打ち切るからTrueになりそうな条件を上の方に書くべきて読んだことがあるなあ >>720 普通の人間ならそうなるだろ? レアパターンを先に評価するやつなんて変わり者 >>721 1、2、3……順とかにするのは普通 頻度順にまではしないことも多々ある read.cgi ver 07.5.1 2024/04/28 Walang Kapalit ★ | Donguri System Team 5ちゃんねる