スキップしてメイン コンテンツに移動

投稿

ACCESSで文字数を規定する書式設定をしてあるテキストボックスをクリックしたときのキャレット位置の操作

タイトルだけ観ると、随分と長い複雑なもののように見えるけど、たいしたことない。 ACCESSのあるフォームに、こういう書式設定がしてある。 書式:"00000" 文字配置:左 この時、テキストボックスの表示幅が5桁を表示するぶんより十分余裕があったとき、その余裕部分をクリックすると、書式で規定した5文字目ラストにキャレットが置かれてしまう。 この時そのまま数字を入力してしまうと、書式エラーで引っかかる。それがユーザーが面倒だ、キャレットを左端、つまり先頭において欲しい、という。 この問題はキーボード操作ではF2を押すとキャレットは先頭に移動するのだが… ユーザーが複数いて、その人全部にそれぞれ同じように説明するのも面倒なんで、問題のテキストボックスにクリックイベントが発生したら、F2をSendKeysで送るようにした。ってはなしで。 SendKyes "{F2}", True

アーリーバインディングとレイトバインディング

はじめに、と後から、というくらいの違いは知ってはいるけど。 改めてどう違うのか?を調べてみた。 書式の違いはこう(VBA) ・アーリーバインディングの例 Dim myApp as Excel.Application Set myApp = Application ・レイトバインディングの例 Dim myApp as Object Set myApp = Application もう一例 Dim myApp as Object Set myApp = CreateObject("Excel.Application") まあ、CreateObjectで書く事が多いよね。 でも、やっぱりアーリーバインディングで書く事には相応の違いがあるそうな。 一つは、たとえばメソッドの存在チェック。 アーリーバインディングでは、"myApp"内に当該メソッドが存在するかはコンパイル時にチェックされる。 一方レイトバインディングではプログラムが実際に実行されるまではチェックがされない。 つまり、動かしてみないと判らない、という事。 開発やテストの事を考えるとアーリーバインディングのほうがやっぱりいいんだろう。

AccessのDfirst関数 その条件式

前にAccessの Dsum 関数について書いた。 それと同類の、Dfirst 関数を今回使った。 Dfirst はレコードセットの最初のレコードの値を取る、というもの。 基本的な記述方法は Dsum も Dfirst も同じ。 関数名("項目名", "テーブル名 or クエリー名", "条件式") ※条件式は省略可 で、今回なんでわざわざ書いたか?というと、前回 Dsum では使用しなかった条件式を与えたから。これはちょっとメモっておきたかったので。 今回 Dfirst をこういう風につかった。 フォームのテキストボックスオブジェクトのコントロールソースに以下を既定 =DFirst("顧客CD","M_顧客マスタ","受注先CD= [p_jyutyusaki_cd] ") 内容としては、同一フォームにある「p_jyutyusaki_cd」というオブジェクトの値を”受注先CD”という、"M_顧客マスタ"テーブルのフィールドのセレクト条件にして、これまた同テーブルに既定されている”顧客CD”の最初の値を返す。 言ってしまえばこれだけなのだが、この『テキストボックスオブジェクトのコントロールソース』として書く際のパラメータ指定の書き方がMSのリファレンスにもあんまり書いてない。 結論から言えば、"受注先CD= [p_jyutyusaki_cd] "という標記になるのだが、最初はVBAでSQL文字列を書くようにテキストの変数をシングルクォートとアンパサントで囲うのか?とかいろいろ書いてみたのだが、通らない。関数の実行結果がエラーになるんだよね。 で、幾度か書き方を変えて試してたどり着いたのが"受注先CD= [p_jyutyusaki_cd] "という書き方でやっとエラーなく通った。 ただし、ここで書いている方法はあくまで、”オブジェクトのコントロールソース”として書くときに、同一フォーム上のオブジェクト値をパラメータにする、という限定された条件である事は改めて記しておく。 これをVBAで書くときなどは多分別の書き方になるはずだ。

Accessで環境変数を使う

今回のお題は、ディレクトリの特定の仕方について。 Accessで処理するファイルを、ある場所、具体的にはユーザープロファイルの”ダウンロード”フォルダからアプリのディレクトリに移動したい。 ただ、”ダウンロード”フォルダはログインしているユーザーによって絶対パスが変わってくる。それをどうするか? 今回の場合、ユーザーのリテラシーがそれほど高くなく、ネットからダウンロードされたファイルを、ユーザー自身がファイル選択ダイアログから選んで指示するのは避ける、という判断となった。 一応、ネットからダウンロードされるファイルの保存先はユーザー別の”ダウンロード”フォルダ、という事は保障される前提。 ダウンロードされるファイル名は名前付けルールにそって、識別子のお尻にタイムスタンプが付く。 ただ、Access側での処理のタイミングの問題で、同時に複数のダウンロードファイルを処理するケースも想定された。 個人的には、バッチファイルを同期でアクセスから実行して…、で良いんじゃない?と思った。 それなら環境変数でユーザープロファイルのパスが取れるから。 でも他からの判断でアクセス内で完結させる方法をとる事となった。 で、結局はWSHの ExpandEnvironmentStrings メソッドを使う事にした。 このメソッドは環境変数(%XXXX%)文字列をあたえるとそれの展開結果を返してくれる。 なんで、ExpandEnvironmentStrings("%userprofile%")とすると、ログインユーザーのユーザープロファイルパスが帰ってくる。 なお、これをAccessで使うには参照設定として「Windows Script Host Object Model」 を追加しないといけない。 また、オブジェクトを使うにはアーリーバインディングで書く必要がある事に注意。 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>...

AccessのDsum関数

#SE 今回、Accessの"Dsum関数"を初めて使った。 先にリンクテーブルを張りなおした!、という案件での事。 明細項目に商品毎の金額があるのだが、その合計をフォームで表示してほしい、というものだった。 最初は明細用のサブフォーム内で、明細レコードに金額を合計したレコードをUnionで一緒に表示しようかと考えていたんだけれど、明細サブフォームのレコード数表示は明細件数を確認するから、そこに影響する方法はダメとなったので代替手段をとった。 これまでならユーザー定義関数を書いて、その中でDAOでSQLを書いて帰ってきた値をテキストボックスに与える、という方法をとっていたんだけど、まあ、他にも方法はないかな?という事で勉強感覚でMSの関数リファレンスを眺めてたら、上記の"Dsum関数"を見つけた、というわけ。 書式 :DSum( フィールド名, テーブル名若しくはクエリー名, 条件 ) 戻り値:指定したレコードのセット (定義域) に含まれる値の合計 "条件"はSQL文でのWhere句。ただし"Where"は含まない 要は、既にACCESSで定義済みのテーブルやクエリーに規定されてるフィールドの合計値をもとめる、ということ。一応条件付けも出来る。 確かにお手軽やね。 今回は、特段条件づけは必要が無かったので簡単に済ますことが出来た。 この関数は既に存在するリソースをそのまま使える場合には都合がいい。 ただ、この目的のためだけに新たなクエリーを規定する必要があるのだとしたら、それはやめて、ユーザー関数でSQLを書いた方がいいと思う。

会社のPCへリモートデスクトップ接続

なんてことはない、備忘みたいなもの。 会社がモバイルPCで仕事できるように、とVPNで社内ネットワークに接続するサービスを提供している。 会社の表向きの説明では、ファイルサーバへの接続だったり、Notes(モバイルPCでは不可)の利用のため、という説明。だから普通の従業員はモバイルにオフィスソフトをいれ、Notesをいれ、社外用のメーラー(Notesは社内専用)をいれてそれをモバイルPCで稼動させている。 しかもこの仕組み、出来が悪くて、VPN接続時には社外専用のメーラでメールを送受信できない。だから社内メールを使うときはVPN接続してローカルのノーツを利用し、社外とやり取りが必要な場合には、いったんVPNを切って、社外用メーラーでやり取りする、というなんとも面倒な仕組み。一応PVNで入らずとも社内メールのやり取りを出来るように、とCACHATTOを使えるようにしてあるが、CACHATTOはアドレス帳が使いづらいうえ、その他のNotesアプリのほとんどが使えない。 よくあるのが、メールにNotesの文書リンクを張ってある事が非常に多いのだが、肝心のリンク先が読めないケースがほとんど。 まあ、家のインフラは従業員の事をどれほどまじめに考えているのか?自分たちがほとんど使うことがないから、こんな中途半端な仕組みで『ちゃんと仕事してます』と知らん連中にアピールしてるんだな。知らん連中は『セキュリティ』という単語で怖気づくからな。でもその実情は穴だらけだ。 それは置いておいて。 で、VPNでアクセスしたとき、社内ネットワークのほぼすべてのリソースにアクセスできる。こんなことをしてみた。 オフィスのデスクトップPCをリモート接続可能な設定にして、それをVPN経由でモバイル経由でログオンする、というもの。 あまり社外に出ることも無く、休みの日に家で仕事する意思もないが、それでも出張先で『あ、あのファイルPCの中だ』というケースはたまにある。そんなとき用に。 オフィスPC 一応よりセキュリティの高いアカウント設定にして、ユーザーも自分以外は接続できないようにしてある。 で、モバイルからはこうやって接続するのね。 後はモバイルのデスクトップにでも設定ファイルを保存しておけばO...

ACCESSでリンクテーブルを張りなおししたら起きた事 #NAME?

先の投稿で『拾い出しシステム』の明細情報を読むために、リンクテーブルを都度張りなおす、という方法について書いた。 今日はその関連で起きた事を書き留めておく。 物件管理番号はメインフォームで指示され、その指示された物件管理番号の明細レコードをサブフォームで表示する、という構造だ。そこで物件管理番号が変わったら、リンクテーブルを張りなおす、という処理を行ったわけ。 最初の内はそれだけでなんら問題なかった。 サブフォームの項目のコントロールソースはリンクテーブルのデータ項目に設定していて、リンクテーブルを張りなおしした後、サブフォームをリクエリーするだけでうまく表示内容が切り替わった。 ただここからが問題だった。 明細レコードには品目コードがある。品目のコードは規格コードと色コードの組み合わせで構成されていて、『拾い出しシステム』ではこの二つは分離して管理されている。 一方基幹システムの品目コードは規格コード+色コード。つまりこのままでは基幹システムに突っ込めない。 そこでサブフォームのレコードソースをクエリーに変更して、基幹システム用の品目コードを演算(規格コード+色コード)するように変更した。 そうしたら、” #NAME?”です。非演算項目は問題なく表示されるんだけれど、演算項目はだめ。メインフォームを開いた一発目はちゃんと演算項目も表示するんだけど、管理ナンバーの変更を行うと演算項目は表示できない。 結局、どう落ち着けたのか?というと、リンクテーブルを更新した後、サブフォームのソースオブジェクトを再定義する方法で安定した。 "sub_meisai"というサブフォーム用のフォーム定義があり、メインフォームでこれまた”sub_meisai”というサブフォームが定義されている。 サブフォーム”sub_meisai”のソースオブジェクトをフォーム”sub_meisai”に定義しなおしている。 =========================================== Me.sub_meisai.SourceObject = "sub_meisai" ===========================================

ACCESSで動的にリンクテーブルの元ファイルを変更する方法

今回の事案は初めてのケースだった。 ある事業で、顧客に対してある種の設計サービスを行っている。 住宅関連なのだが、ハウスメーカーが、こういう設計の住宅、といった図面をよこしてきて、その図面からうちの商材をパーツごとに必要な数を拾い出しして見積もりを行い、販売する、というものだ。 住宅、という事でまあ『物件』と称され、上記のサービスを実現しているのが『物件拾い出しシステム』と呼ばれている。 で、この『物件拾い出しシステム』、全物件のヘッダー情報はファイルサーバー上の.mdbファイルに保管されているのだが、どの商材をいくつ、あの商材をいくつ、という『拾い出し』した結果の明細情報が、物件の管理ナンバーをファイル名とした別の.mdbファイルに格納されている、という構造なんだ。 今回受けたオーダーは、この『物件拾い出しシステム』の情報を使って、SAPScriptで受注伝票を突っ込む、というもの。開発プラットフォームはAccess。 で、タイトルのとおりの事をしないといけない破目になった。 各物件別の明細情報はファイル名以外はテーブル構造やテーブル名は共通。ファイル名は先に書いたとおり物件管理番号で、配置されるディレクトリもルールで決まっている。 そこで、ヘッダーファイルから管理番号を選択すると、明細情報を呼び出すためにリンクテーブルの接続先ファイルを各明細別mdbファイルに切り替える、という処理をした。 具体的にはこう。 =========================================== Const conmyDbPath = "\\サーバー名\物件データ" '明細ファイルへのパス生成文字列 Const conmyTbName = "T_拾い数量合算"          '明細情報へのリンクテーブル Dim dbsSys   As DAO.Database 'データベースオブジェクト Dim myDb As DAO.Database '明細用データベース Dim meisaiTb As DAO.TableDef 'テーブル(T_拾い数量合算) Dim pKanriNo As String '物件管理ナンバー pKa...

【評価中】Weava

最近、『 Weava 』というサービスを知って、試し始めている。 WEBページの文章をストック出来る、Chrome の機能拡張として提供されているサービスだ。 使い方はシンプル。ストックしておきたい文章を見つけたら選択して右クリックから"Weave Highliter"→"Highlit" を選択すると、そのページとハイライトした部分がサービスにストックされる、というもの。 ハイライトは同一ページに複数設定でき、それがサービス内でちゃんと管理されている。 ページを選択すると、そのページで具体的にどういう文にハイライトしたのか、が個別に識別できるのだ。 また、そのページをどのフォルダで管理するかも選択できる(階層化もOK)。 なかなかいいサービスかな。特に仕事で特定のテーマについて調べる場合には重宝しそう。テーマに沿ってググッて、使えそうな部分をハイライトしてクリップしておく。 ある程度クリップがまとまったら、ハイライト部分を寄せ集めて一つの形の元を作成する、なんて使い方にいいかも。 もうちょっと試してみよう。

VBSをタスクスケジューラーで起動したときのホームディレクトリ

やおらVBSでの引数処理を書いたのはほかでもない。 先に作成したソニー生命の巡回スクリプトをタスクスケジューラーに登録して実行したら、いまいちなのだ。 スクリプトを直接指示して実行しているのだが、その作業ディレクトリがエクスプローラーからダブルクリックで起動した時と違う。 上記の場合、スクリプトのあるフォルダにログファイルが出力されるのだが、タスクスケジューラーから起動すると、C:\Windows\System32 にログファイルが出力されてしまうのだ。 そこで、本来出力したい場所に出力できるよう、タスクスケジューラーで引数としてログファイルのパスを与える事にした。 これで上手くいった。

VBS で引数を受け取るサンプル

WScript.Arguments に引数要素が配列で格納されているので、これを取り出す。 =========================================== '############################# 'パラメータ=オーダーIDの取り出しとセット '############################# Dim oParam 'パラメータオブジェクト Dim strPrm0  'パラメータ要素格納 Set oParam = WScript.Arguments strPrm0 = oParam(0) Wscript.echo strPrm0 =========================================== これを引数あり、引数なしでそれぞれ実行してみる。 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ >cscript.exe test.vbs a a >cscript.exe test.vbs test.vbs(9, 1) Microsoft VBScript 実行時エラー: インデックスが有効範囲にありません。 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ strPrm0 = oParam(0) の場所で怒られている。 引数なしで起動した場合には相応の対応をしたい。 そこで、上記を書き換える。 WScript.Arguments のCount ポロパティの値をチェックして動作を切り分ける方法。 =========================================== '############################# 'パラメータ=オーダーIDの取り出しとセット '############################# Dim oParam 'パラメータオブジェクト Dim strPrm0  'パラメータ要素格納 Set oParam = WScript.Arguments ...

郵便局HPでの郵便番号検索

郵便局HPでの郵便番号検索の利用方法。 http://www.post.japanpost.jp/cgi-zip/zipcode.php?addr=任意の住所(番地は含まず) このURLで呼び出すと呼び出せば、ヒットした地名が表示され、その地名をクリックすると郵便番号が判る。但し番地まで与えてしまうと、Not Found になってしまう。 これが使い出がいいのは、難読地名の郵便番号を得たい場合だ。 上記で市区町村までの住所を与えると、その市区町村の地名のリストを出力してくれる。 文書で指示はされているけど、住所の読みがわからず文字入力に難儀する場合などにたすかる。 この表記はブラウザのURLに直接入力するだけでなく、コマンドラインからでも有効だ。 ブラウザアプリ http://www.google.co.jp/maps/place/任意の住所 ただ一つ困った事がある。文字コードの扱いのせいだと思うが、IEだと文字化けして Not Found になってしまう。少なくとも私の環境ではIEではこの方法が取れない。

Google Map で任意の住所を表示させる方法

グーグルマップで、任意の住所を表示させる事が出来る。 http://www.google.co.jp/maps/place/任意の住所 このURLで呼び出せば、番地まで指定してあればその番地を、町名・字までならその区域を色分けした形で表示する。 この表記はブラウザのURLに直接入力するだけでなく、コマンドラインからでも有効だ。 ブラウザアプリ http://www.google.co.jp/maps/place/任意の住所 これがいいのは、指定した住所の地図上の位置だけでなく、郵便番号も返してくれるところだ。住所は記載があるけれど、郵便番号がない。だけど物品の配送手配には郵便番号も与えないといけない、といった場合に地図と郵便番号の検索に使っている。

対処例:Accessフォームでチェックボックスが思うように設定できない

開発プラットフォームとしてAcccessという事は多い。 そして何気に不思議な動作をする事が多いのも事実。 今回であったのは、フォームに置いたチェックボックスが、フォームを開いた際に思ったように振舞ってくれない、というもの。 このチェックボックスは規定値=FALSEで設定してあって、人の操作以外でこのチェックボックスの値は操作していない。 そしてこのチェックボックスを置いたフォームを開くと… 問題のチェックボックス、チェックがついた状態で描画される!!! こまったチャンである。 時折は意図したとおりにOFFの状態で開く場合もあるものの、まれ。 ここはしっかりユーザーの操作(チェックボックスをONにする)に基づき、関連の項目を入力してもらう、という動作をさせたいし、また他へのI/F項目でもあって、しっかりさせたい。ちなみに、TripleState プロパティは Falseに設定してある。 簡単にググッてみたものの、ちょっと同様の事例や対処は見つからず。いくつか試したが、うまく行かない。 で、結論から書くと、こういう対処をした。 Form_OPENイベントの際に、問題のチェックボックスに以下の操作を実行 ・問題のチェックボックスにフォーカス設定 ・問題のチェックボックスに対して、SendKeys でスペース(" ")一文字投げつけ ・問題のチェックボックスの Value 値を確認。True の場合、もう一回SendKey でスペース(" ")一文字投げつけ 発想としては、チェックボックスがカレントな状態のとき、スペースキーで値が操作できる事を思い出し、ぶつけてみた。 でも、実は最初はうまく行かず。 はて? で、 SendKeys のリファレンスを改めて眺めて、 Wait オプションがある事を思い出した。 解説するまでもないが、これが True の場合、そのキーが処理されるまでVBAは次の実行をまつ。デフォルトでは False で実行される。なので、Accessが、なげつけられた?(いや、自分で自分に投げているわけだから…)スペースキーを受け取る前にVBAが進んでるか?と思い、以下に書き換えてやってみた。 SendKeys " ", True ...

ロボット例:ソニー生命個人ページから変額保険の情報を収集する

VBSでIEを操作して仕事をさせるロボット ソニー生命の個人ページにアクセスして、変額保険の契約者貸付金額と増加保険金額を複数の契約から収集し、その合計額をCSVファイルに出力させるロボット。 人に見せる事を前提に書いてないので美しくない。 当然動作保障なし、サポートもなし。

サンプルスクリプト:IEでクリックボタンを連続処理する(VBS)

VBSでIEを操作する。 選択可能なボタンを連続的にクリックし、リンク先での処理を行う。 但しボタンはクリック可能なものと不可能なものが存在し、 且つリンク先は別ウインドウで開くと遷移エラーとなるのでシングルで処理する必要がある場合の処理。