お世話になっております。
accessのフォームで縦スクロールバーをマウスでつかんだとき、 レコード:13/44 のような表示が出てくるのですが、そのときの値を取得したく、いろいろネットで調べていたら下記のヤフー知恵袋を発見しました。
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q14115400469
まさにこの質問者と同じことをしたいです。
しかし、ベストアンサー(hatenaさん?)のとおり対応しようとしたところ、Office365の環境では「前のバージョンを開くことはできません」とエラーがでて、うまくインポートすることができませんでした。
Office365の環境で、スクロールバーの値を取得する方法はありますでしょうか?
ご教授よろしくお願い致します。
スクロールバーの「位置」を知ることができるプロパティがあります
Form.CurrentSectionTop プロパティ (Access)
このプロパティで調べてみてください
hiroton様
ご返信ありがとうございます。
CurrentSectionTop は試しましたが、うまくいきませんでした…
スクロールバーを一番上にして、レコードを1に合わせた状態で値を取得すると450
スクロールバーを一番上にして、レコードを13に合わせた状態で値を取得すると5130
となります。
希望は、どのレコードにいてもスクロールバーが同じ位置なら、同じ値が欲しいのです。
(画像で言うとスクロールバーが一番上なので「1」の値が欲しい)
お手数をおかけしますが、よろしくお願い致します。
このプロパティで調べて(Web検索して)みてください
【Access】帳票フォームでRequeryを行ってもレコードの表示位置が変わらないようにする(ほそぼそプログラミング日記さん)
hiroton 様
度々のご返信ありがとうございます。
ただ申し訳ございません、求めているものとは少し違っておりました。
上記の方法で試したところ、たしかにレコードは同じ位置になるのですが、表示位置が一番上にきてしまいます。
スクロールバーの値さえ取得すれば、GoToPageを使用して実行後も同じスクロールバーの位置(画像でいうと6が一番上の位置)にできるのではないかと思い、悩んでおります。
うまく伝えられず申し訳ございません。よろしくお願い致します。
hiroton 様
大変申し訳ございません。上記の方法を不完全な状態で試しておりました。
(curTop = Me.CurrentSectionTop が抜けていました)
ちゃんとした方法で行ったところ、うまくいきました。
ちなみにスクロールバーの値はやはり取得するのは難しいものでしょうか…?
「直接」は難しいと思います
ただ、左の数字は
で取得可能。右の数字はレコード総数なので
とすれば同じ内容になると思いますが、これではまずいですか?
hiroton 様
返信遅くなり申し訳ございません。
やはり難しいですか…承知しました。
たしかに上記の式でほぼ取得可能なのですが、場所によって1つずれる現象がございました。
私なりに調べたところ
の部分が原因らしく、
curTop / Me.Section("詳細").Height の値が「●●.998…」等になる場合、そのまま小数点が切り捨てられてしまい1つずれてしまいます。
ならば
で、四捨五入すれば良いかなと思ったのですが、そうすると今までOKだった箇所が1つずれたりと、うまく安定してくれません。
curTop / Me.Section("詳細").Height の値によってずれたりずれなかったりするため、単純にスクロールバーの整数の値を取得できれば確実だなと思い質問しました。
ただずれるとしてもひとつ程度なので、とりあえずはこれで運用していきたいと思います。
ご教授ありがとうございました。
スクロールバーをマウスでつかんだとき出てくるそれをツールチップと呼びますが、ずれとは以下のどのような状態でしょう?
1.「見た目」とツールチップは同じでVBAの結果にずれがある
2.「見た目」とVBAの結果は同じでツールチップにずれがある
(1)の場合コードに不備があるのだと思います(hirotonはリンク先のコードを検証していません)
(2)の場合はスクロールバーが何を基準に数字を出しているのかわからないのでCurrentSectionTopを使った方法では無理なのかもしれません
『「直接」は難しい』についてですが、出来る出来ないで言えば出来ると思います。質問のリンク先で言われているようなことを今の環境に合わせて実装すればいいです。「windows api」「スクロールバー」「ツールチップ」等のキーワードを組み合わせれば情報を得られるでしょう
ただ、キーワードを見てわかるようにほぼACCESSとは関係ない内容になるのでhirotonとしてはこの掲示板でどうこうするつもりはありません
これについて情報が欲しい場合は他の方の回答を待ってください
難しいことに手を出そうとしているようだったのでキーワード(Form.CurrentSectionTop)だけ出せばある程度作れる能力があるのかなと思っていましたが、そうでもなさそうですね
うまくいかないパターンのそれぞれのプロパティの値と実際に見えるレコードの番号、ツールチップの値を提示してください。このような計算において丸め処理(「Int()」や「/」での計算も)は繰り返せば繰り返すほど後々大きな誤差になります
この処理は、理屈を考えれば単純で、「積み上げた積み木を数えるようなもの」なので計算結果で小数点がでるというのが何かちょっと違うなぁと感じます(普通、積み木が3.998個重なっていますとはならない)
リンク先コードでは
という処理が合って、ここで丸め処理をしているので何か影響してる可能性があります。これが必要な処理なのか考えてみてください。(もしくは上述の通り情報提供してください)
hiroton 様
色々とご説明いただきありがとうございます。
まだまだ勉強不足でございました。
1.「見た目」とツールチップは同じでVBAの結果にずれがある
に該当します。
ツールチップについてはACCESS外の話になるとのことので、また別で考えさせていただきます。
以下、リンク先のコードにそって情報提示致します。
うまくいく場合
ずれる場合
ご指摘どおり丸め処理がずれていると思います。
うまくいく場合 Int(3180 / 397) = 8.0100...=8 OK
ずれる場合 Int(3570 / 397) = 8.992...=8 (本当は9の値が欲しい)
どのように修正すればどんな条件でも一致するか悩んでおります。
すみません、補足です。上記のように
の高さだと四捨五入 Int((curTop / Me.Section("詳細").Height)+0.5) をすれば成り立つのですが、
の高さだと四捨五入すると逆にずれ、どの場所でもそのままで成り立つという現象になり、なかなか安定せずに悩んでおりました。
なんだか丸め誤差といえるほど小さな誤差じゃなさそうですね
ヘッダーと詳細セクションの間、詳細セクション同士(レコード同士)の間に高さがあるのかもしれません
後ほど検証してみようと思いますが、取り掛かりまでしばらくかかりそうです(hatenaさんが素晴らしい回答をされているので甘えます)
そもそも詳細セクションがいくつ並んでるかを求めるという話なので、詳細セクション合計の高さを詳細セクション個別の高さで割ればレコードの数になるはずです
CurrentSectionTop
はフォーム上端からの高さを返すのでヘッダー分を引かなければなりませんが、「レコード分に換算して引く」という手法がよくわかりません。単純にCurrentSectionTop
からヘッダー分の高さを引けば詳細セクション合計の高さが残るはずです計算式は
((ヘッダー + レコード数 * height) - ヘッダー) / height
となり、そもそも小数点が出る計算がおかしいというのを焦点にしたかったんですが、結果は検証してみてですねhiroton 様
考察していただきありがとうございます。
hatena様のご回答により当初の目的は果たしたのですが、まだモヤモヤがぬぐい切れていないので私もhiroton様の考察をもとに検討させていただきます。
恥ずかしながらリンク先のコードは世に出回っているものなので必ず正であるという固定概念があり、小数点が出る計算に対して「なぜ」という考えに至りませんでした。
hiroton様のおっしゃる通り、求めたい値に対してなぜその計算をするのか理屈を考えながら進めていきたいと思います。
hiroton 様
ヒントをもとに検証したところ、どんなヘッダ高さ、詳細高さでも安定して先頭レコードを表示することができました!
リンク先のコードよりもシンプルかつ分かりやすいコードになったと思います。
こちらで問題ないでしょうか??
Windows API を使う方法です。
標準モジュールに下記のコードをコピーしてください。
フォーム上にコマンドボタンを配置して、下記で表示されるようです。
Office2019 64bit で動作確認。
64bit対応に書き換える時間がなかなか取れなかったので回答が遅くなりました。
hatena 様
ご返信ありがとうございます。
上記コードをそのまま試したところ、無事に動作確認が取れました。
わざわざ64bit対応で書いていただき、大変ありがとうございます。
正直コード内容については一読で理解できそうにないので、じっくり読まさせて頂きます。。
下記コードにて検証してみました
ヘッダー無し、詳細高さ1.575cmの場合
ヘッダー高さ0.975cm、詳細高さ1.575cmの場合
ヘッダー高さ0.6cm、詳細高さ1.575cmの場合
ヘッダー高さ0.801cm、詳細高さ1.575cmの場合
ヘッダー高さ0.6cm、詳細高さ2cmの場合
ヘッダー高さ0.801cm、詳細高さ2cmの場合
ヘッダー高さ0.801cm、詳細高さ0.801cmの場合
うーん、これは予想しない(困った)結果に・・・
どうやら
CurrentSectionTop
はセクションの高さに応じて補正が入るようです。今回得られた補正量は高さに応じてこれは、一見ばらばらのようですが「15」単位で四捨五入されています
ACCESSは各セクションの高さをTwipで保持していますが、画面の表示はPixel単位でなければなりません。windowsの標準dpiは96なので、Pixel単位(
1Pixel=15Twip
)で四捨五入されているわけですね>> 9のずれるパターンもこの計算を当てはめれば
正しく結果が得られます
以上のことから
のように、正しく補正を入れれば間違いのない答えが得られます
この方法の問題点
dpiによって結果が変わる
ほぼ決め打ちでも問題ないところですが、正確を期すならdpiの取得が必要です。そこまでするとACCESSの埒外になってしまいます・・・
または、実際にレコードを移動させてCurrentSectionTopを取得し、差を吸収するような仕組み(表示上の詳細セクションの高さを求める仕組み)が必要でしょう
>> 15の回避策は大雑把ながら見どころの有る方法だと思います
96dpi(1Pixel=15Twip)の場合のずれは±7で20レコードあれば最大140Twipずれる可能性があるということになります。このとき、詳細セクションの高さが300Twip程度あれば140Twipずれても四捨五入で欲しいレコードの位置を求めることができます
Macのdpiは72だそうです(古い情報ですが)。この場合同様に考えるとずれは最大±10で20レコードだと200Twipずれる可能性があり、高さが300Twipの場合、高さの半分以上の誤差がでるので四捨五入すると1レコード以上の差になってしまいます。しかしながら、この計算でも14レコードまでであれば正確なレコード数になります
限定された範囲では確からしいことが保証できるので
のような感じで対応してしまうのも無くはないかなと思います
カレントレコードが変わる
コード以前の問題ですが、CurrentSectionTopの仕様としてカレントレコードが表示エリア内に存在しないとちゃんとした数値が得られません。カレントレコードを変えたくない場合(編集中の場合・レコード移動時イベントを不用意に発生させたくない場合)や、またはカレントレコードを元に戻す手間などが問題になるかもしれません
windows apiを使った手法はこの問題に悩むことがないのもいいですね
hiroton 様
非常に細かくCurrentSectionTopの仕組みまで分析していただきありがとうございます。
15単位で四捨五入され、解像度の話まで発展するとは想像すらしませんでした‥
正確なdpiの取得をしないと成り立たない繊細な動作をしたいわけではなく、
また CurrentSectionTop を取得する際は必ずカレントレコードが表示エリア内に存在している作りにはなっているので
15単位で補正するやり方でいきたいと思います。
(単純にwindows apiを使った手法が一番とは思いますが…)
accessは奥が深いですね。まだまだ勉強不足を痛感させられます。
hatena様 hiroton様 この度はご教授いただきありがとうございました。大変助かりました。