VBA店長のひとりごとパソコンショップT&A店長の奮闘記録ですaccdeファイル作成で苦労した原因はACCESSのバグだった!約1年半ぶりのブログ更新です。AccessでのPC-POSレジ開発もいよいよ販売準備段階になっており、配布するためのaccdeファイルを作成しようとしていました。セットアプリの「商品管理」の方を試しました。すると、accdeファイルはエラーも無くすんなり作成できたのですが、起動するとデータベースに接続できていませんでした。accdbファイルの場合はちゃんと接続できているのに何故か?例によってインターネット検索しました。今回のアプリは、データベースにADOで接続する設計にしていますが、その場合、通常はADOライブラリの参照設定を追加してプログラミングしますが、見つかった情報によると、参照設定しない方法でコーディングしないとaccdeでは動かないらしいので、その部分を変更しました。その結果、無事accdeでも動くようになりました。それで次にPOSレジの方も同様に変更し、accdeを作成しましたが、今度はそれでもデータベースに接続できていませんでした。仕方なくまたネットに頼り、3つくらいの方法が見つかったので、それを全て試しましたがだめでした。自分なりに商品管理とPOSレジのコードを比較し、いろいろ変えてみましたが、だめでした。ソフト開発をやっていると、いつも壁に突き当たります。その壁を乗り越えて、ソフトがうまく動いたときに得られる達成感が大きいので、この仕事が好きなのですが、壁を乗り越えられない間は、寝床に入っても考えることが多く、常に頭の中はそのことで一杯です。自分の持っている知識と経験で解決できない時は、結局他人の知識・経験に頼らざるを得ません。ネットで検索する場合、日本語の単語を入力して探すことが多いと思いますが、その場合、検索結果に出てくるサイトは基本的には日本国内のサイトです。日本は小さい国で、日本国内の情報も「井の中の蛙」です。英単語だけで検索すると、アメリカのサイトの情報がいろいろ出てきます。この時代便利なのは、英語のサイトでも自動翻訳してくれます。おかしな日本語訳も時々ありますが、だいたいは内容を理解できます。日本より人口も多くパソコンを使っている人も多く、Accessで開発している人も多いので、同様の問題で困っている人の質問サイトも多くありました。日本のサイトで示されていることと同じ方法を示している人も多かったのですが、読んでいるうちに見つかった内容が、「空のSubルーチンを削除したら解決した」というもので、それをやって解決したので、お礼を書いている人が一杯いました。私もそれをやりました。したら何と、accdeでもちゃんと動きました!何という解決法でしょう?Microsoftには「ええかげんにせえよ!」と言いたいです。明らかにAccessのバグです。x86で、サービスパックも適用しています。2019でもAccdeを作成してみましたが、だめだったので、このバグは現在も残っているバグだと思われますが、日本でももっと騒がれてもよさそうな問題のはずなのに、日本のサイトには一つも無かったことが逆に不思議でした。それだけAccessで開発している人が減ったということでしょうか。何はともあれ、大きな壁をまた一つ乗り越えられ、ほっとしました。0Pagetopタブコントロールでキー入力イベントが発生しない!?商品管理ソフトではタブコントールを使って、[商品検索]画面と[新規入力]画面を切り替えています。[商品検索]で検索キーワードを入力し[検索実行]ボタンをクリックすると検索結果を表示できます。ここでも、マウスを使わずキー入力で検索実行できた方が早いので、ショートカットキーを設定しようとしました。フォームの[キーボードイベント取得]を「はい」に設定してあるのですが、キー入力イベントが発生しないのです。見落としがないか何度もコードをチェックしましたが、ありません。そこでいつものようにWEBを探したところ、同じ問題を指摘している記事がひとつだけ見つかりました。2010ではこの問題が起こり、2007では起こらない模様です。私の開発環境も2010です。結局、解決方法は載っていませんでした。しかたがないので、他の方法で目的を達成することを考えることにしました。検索タブの中の一部のテキストボックスでは、数字しか入力を受け付けないようにKeyPressイベント・プロシージャを使っており、同じ機能を別モジュールでもよく使うので、標準モジュールに記述し呼び出していますが、ちゃんと機能していました。いうことは、標準モジュールを使い関数的に作ればうまくいくかもしれないと思い、やってみたら正解でした。0Pagetop開いたフォームがアクティブにならない現在運用中のPOSレジソフトを少し変更することにしました。従来は、販売処理完了後メッセージボックスを表示させ、確認後レジ画面を初期化していたのですが、メッセージボックスは小さくて目立たないので、新しくフォームを作りそこにお釣りを表示させることにしました。それ自体簡単なことなのですが、問題が発生しました。メッセージボックスの時はそれがアクティブになっていたのに、フォームに変えたらアクティブにならないのです。アクティブだとキー入力を受け付けますが、そうでないと受け付けず、マウス・クリックが必要となるのです。レジ処理はできるだけ迅速に行う必要があり、できるだけマウスを使わずにキー操作でできるように設計しています。VBAからではなく単純にフォームを開くと、当然ですがそのフォームがアクティブになります。メインフォームのVBAからそのフォームを開くとアクティブにはならないのです。試行錯誤し考えた結果、フォームを開く元のイベントがGotFocusだったからということに気づきました。メイン・フォームのコントロールがフォーカスを取得したときのイベント・プロシージャで他のフォームを開いてもフォーカスは移るはずがありません。いうことで、別のイベント(キー入力)プロシージャに処理を移し、そこから開くようにしたらアクティブになりました。私よりも上級のプログラマーなら当たり前の話かもしれませんが、意外な落とし穴でした。カスタマイズ」等のキーワードで私もいろいろ調べましたが、あまり分かりやすいサイトは見つかりませんでした。そこで、備忘録を兼ねて解説したいと思います。2007から採用されたもので、従来のサブメニューとツールバーを合体させたものです。私も含めOfficeを2003以前から使われていた人は、2007でこのリボンに変わり、自分が使いたい機能がどこに行ってしまったのか分からず、苦労された方も多いのではないでしょうか。(私もそうでした)前回の記事で紹介した「商品管理」アプリにも独自リボンを追加しています。USysRibbonsというシステムテーブルを作成します。システムテーブルは普段非表示になっているので、表示させる必要があります。この部分の詳しい手順は、マイクロソフトの「リボンをカスタマイズする」にあります。次に、このテーブルのRibbonXMLフィールドにXML文を記述します。先述のサイトにもある程度XML文についての説明やサンプルがありますが、VBAモジュールとの対応などもっと詳しく説明した日本語サイトが無く、探していたら、英語サイトが見つかりました。idタグが入れ子になっています。idタグのlabel=で指定している文字列が新しいタブの名前です。私のソフトでは、「マスター管理」と「設定」がそれになります。タブの中を仕切ってグループを複数作れます。idタグのlabel=の部分がグループ名となります。「マスター管理」タブの中に「仕入先」と「商品分類」のグループを作りました。idタグの中のlabel=がボタン名で、imageMso=がアイコンの名前(種類)です。Case文の各Caseで指定されている文字列と対応します。ボタンをクリックするとそのCaseの命令が実行されるわけです。idに重複は許されません。最後にアイコンの名前ですが、何でもよいわけではなく、存在するアイコンの名前を指定する必要があります。Resources\2007OfficeIconsGalleryにOffice2007IconsGallery.xlsmが作成されます。1~9までのアイコンがあります。1~3までは普通サイズ、4以降はスモールサイズのアイコンです。好きなアイコンをマウスポイントするとそのアイコンの名称が表示されるので、それを先のXML文のimageMso=で指定します。IDsからダウンロードし展開すると、複数のExcelファイルができますが、AccessRibbonControls.xlsxを開くと英語ですが各コマンドの記述法が表になっています。0PagetopTreeViewコントロールに挑戦POSレジソフトも開発・使用中ですが、それに連携する商品管理ソフトも作成しています。完成に近づいてきました。画面左側に商品分類ツリーを設けているところが”ミソ”です。VBAのTreeViewコントロールを使いましたが、だいぶ苦労しました。[SelectedImage]の式の中の[Text]が登録するノードの表示名で、[Key]がノードを識別する名前になります。このKeyをTextと同じ内容にしている例があるのですが、Key値は重複が許されません。分類ツリーが細分化していくと、どうしても同じ分類名が出てくる(例えば、LANケーブルにも2mがあるし、USBケーブルにも2mがある)可能性があるので、Text値は重複しますが、Key値は一意の値にしないといけないのです。そこで、同じ親の中には重複する子供の名前は無いので、[親名]&[子名]をKey値としました。分類の親子関係が必要になるので、分類テーブルには親分類のフィールドを設定しています。分類は5階層まで設定したので、Do~Loopを5重の”入れ子”にし、登録部分のコードが出来上がりました。このツリー・ビューの目的は、分類名をクリックするだけでフィルタをかける(商品を絞り込む)ことです。画面右下の[検索]タブでも複合検索はできるのですが、分類だけで絞り込み、価格を比較するということはよくやるので、この機能があると大変便利です。ノードをクリックしたときのイベントが、TreeViewのNodeClickイベントなのですが、ここで失敗したのは、このイベント・プロシージャを一から入力して記述してしまい、エラーが出てしまったことです。見直しましたが、構文には間違いはありません。プロシージャの中に何も記述しなくてもエラーになり、プロシージャ全体をコメントアウトするとエラーがでません。フォームのTreeViewのプロパティのイベントの中にクリック時が無いので、「そもそもクリック時イベントはAccess2010で非対応になったのかな?」とか思ったり、2010にTreeViewに関するバグがあるような情報を見つけたので、更新をかけたりしましたが解決しませんでした。そこで、このプロシージャ部分を一旦削除し、VBAウィンドウのオブジェクト欄からTreeViewを選択し、プロシージャ欄からNodeClickを選択して作成しました。したら、エラーが出なくなりました!非常に単純で基本的なことなのですが、同様の原因でコードがうまく実行できないことがありました。プログラミングに慣れてくると陥りやすい”落とし穴”だと思います。ノードをクリックしたときに得られるプロパティの中に[FullPathプロパティ]があり、そのノードまでのフルパスを返します。インク」という文字列が得られます。この文字列を操作することによって、その分類の親分類名を全て得ることができます。検索をかけるための条件は整ったので、NodeClickイベントの中身を書いていくわけですが、商品テーブルと分類テーブルを結合して検索する必要があるので、SQL文の”SELECT~JOIN~”を使ったのですが、ここでまたつまずきました。「JOIN式はサポートされません。」と叱られてしまったのです(;_;)これも原因が分かるまで苦労しましたが、その原因は”ずぼら”でした。単純なSELECT文の中では、各フィールド名の記述だけでよいのですが、複数のテーブルを結合する場合は、[テーブル名].[フィールド名]というように記述しないといけないのに、フィールド名が重複していなければよいと思い、テーブル名を省略していたのです。これも基本的なことなので、面倒でもちゃんと基本に則らないとダメですね。