2013年5月18日土曜日

Excelでコンテキストメニューを実現する方法

Excelを使って他の人にデータを入力してもらうフォームを作成する時に、コンテキストメニューの形でリストメニューを表示できると入力に間違いが少なくなるのにと思うことがあります。つまり、左側のセルに入力したデータによって、入力するデータの選択肢となるリストの内容を変化させたいと思うことがあるのです。試行錯誤の末、1つのやり方がまとまったので、ここで紹介します。例として、地域名と県名を入力するExcelを用意しました。

選択肢となるリストを準備し、名前付きセルにする

今回の例ではまず地域の選択肢となるリストとして[第一階層]を、県の選択肢となるリストを3種類[東北]、[四国]、[九州]を準備します。準備ができたら、そのリストの選択肢部分を名前付きセルとします。

名前付きセルを設定するには[数式]タブの中の[名前の管理]ボタンをクリックします。

セルの名前はリストの名前と一致させるようにしてください。設定後のダイアログは以下のようになります。

データ入力規則でリストを表示するようにする

次に地域のデータを入力する部分の設定をします。まずデータ入力可能とする部分を選択します。

次にデータ入力の規則を設定しますが、これは[データ]タブから[データ入力規則]ボタンをクリックします。

[入力値の種類]を[リスト]にし、[元の値]を=第一階層とします。

これで名前付きセル「第一階層」の内容が選択肢として表示されるようになります。

左側のセルの内容により表示するリストを切り替えるためINDIRECTを使う

次に県名データを入力する部分の設定をします。今度はデータ入力可能とする部分のセルを1つだけ選択します。

次にデータ入力の規則を設定しますが、地域の時と同様に[データ]タブから[データ入力規則]ボタンをクリックします。[入力値の種類]を[リスト]にし、[元の値]を=INDIRECT(G4)とします。G4は選択したセルの左隣のセルになります。

名前付きセルとセル参照をうまく組み合わせるのがこのやり方のキモになります。設定が終了したらこのセルをコピーし、入力可能な他のエリアにペーストし完成です。

注意点

このやり方はExcel 2007とExcel 2010でしか確認していません。また、この例の地域部分に入力してから県名のデータを入力するという順番を前提にしています。県名の部分を先に入力することはできません。


2013年5月11日土曜日

Officeアプリケーションを操作するPowerShellスクリプトをタスクスケジューラから自動起動する方法

インターネットを検索すると
  • Excelを操作するPowerShellスクリプトの書き方
  • PowerShellスクリプトをタスクスケジューラから起動する方法
について説明しているブログや記事を見つけ出すことはそれ程大変ではありません。そのため、表題の件もちょっと検索して情報を集めれば実現できそうですが、実際にやってみるとどツボにハマります。
  •  OfficeアプリケーションをCOM経由で操作する
  • タスクスケジューラから起動
の条件が揃うとうまく行かないようなのです。

PowerShellから動作するスクリプトがタスクスケジューラから起動すると正常に動作しない

作成したスクリプトは複数のPowerPointファイルを1ファイルにまとめるスクリプトで、やりたかったのは、週に1度ある時刻にこのスクリプトを自動的に実施するということでした。PowerShellスクリプトでPowerPointファイルを処理する方法についてはインターネット上を検索すれば情報が得られます。大きな苦労をすることなく1ファイルにまとめるスクリプトは完成し、PowerShellから起動する分には問題なく動作していました。ところが、同じスクリプトをタスクスケジューラから起動するように設定しても、まったく目的の処理がされないという事態に直面したのです。

PowerShellスクリプトをタスクスケジューラから正常起動できているか確認

最初は自分の単純な設定ミスだと思っていたため、タスクスケジューラでの設定をいろいろ調べて調整してみたのですが、どうもそれでは解決しません。どうも簡単な問題ではないことが分かってきたので、地道に問題の切り分けを行うことにしました。まずは簡単なテキストファイルを作成するPowerShellスクリプトを作成し、それをタスクスケジューラから起動してみました。すると何の問題もなく動作します。これでタスクスケジューラからスクリプトがキックされていないということは無いことが分かりました。

New-Object -ComObjectに失敗している

今回の処理を実現するため、PowerShellスクリプトからPowerPointファイルを操作するのにCOMを使っています。問題の切り分けの次の段階としてPowerPointを起動し、ファイルをオープンするだけのスクリプトを作成し、タスクスケジューラから実行するようにしてみました。すると、今度は挙動が変わってしまい、上手く動作しません。更に絞り込んでいってみると、COMオブジェクトを作成する"New-Object -ComObject"が失敗し$nullを返していることが分かりました。ここまで分かれば、インターネットでソリューションを探すことができるだろうと検索してみましたが、なかなか同様の問題が見つかりません。まれに見つかっても(操作対象がPowerPointではなくExcelだったりするものの)質問があるだけで、解決に至っていないものでした。

解決方法はフォルダを作るだけ?

すぐに問題は解決しなかったため、思いついた時にいろいろなキーワードで検索していました。最終的に何のキーワードで検索した時に引っかかったのかは覚えていませんが、英語のサイトで回答が書かれているものが見つかったのです。その内容は
C:\Windows\System32\config\systemprofile\Desktop
C:\Windows\SysWOW64\config\systemprofile\Desktop
(試したのはWindows 7 64bit環境になります)
というフォルダーを作成すると良いというものでした。フォルダー作るだけ?何でこのフォルダー?と頭の中には疑問符が幾つも浮かびましたが、これしか情報が無かったので実際にやってみることにしたのです。

権限を変更したら動いた

実際にフォルダーを作成して挙動が変わるかどうかを試して見ました。元の情報にTypoがあったりして、いろんなパターンを試す必要があったのですが、結果的にはフォルダーを作成するだけでは目的の動作をするようにはなりませんでした。ただし、この"Desktop"フォルダーを作成するのに管理者権限が必要そうなメッセージが表示されたので、もしかしたら実行権限の問題があるかもと思いタスクスケジューラの設定を変更しました。





具体的には「最上位の特権で実行する」にチェックを入れて試したところ、問題切り分け用に作成したスクリプトが狙い通りに動作するようになったのです。徐々にスクリプトでやる内容を増やしていき、最終的には当初の目的のスクリプトが正常に動作することが確認できました。
何故この"Desktop"フォルダーを作成すると問題が解決するのかの理由も調べてみましたが、未だに分かっていません。もしかしたら、今回の私の環境ではたまたま動作するが、一般環境で必ず動作することをMicrosoftが保証していない設定なのかもしれません。

注意点のまとめ

Officeアプリケーションを操作するPowerShellスクリプトをタスクスケジューラから自動起動するには、
  • Windows 7 64bit版では以下の2つのフォルダーを作成するC:\Windows\System32\config\systemprofile\Desktop
    C:\Windows\SysWOW64\config\systemprofile\Desktop
  • タスクスケジューラからスクリプトの実行は「最上位の特権で実行する」設定とする必要があります。

ルーチンワークは自動化しよう

そもそも何故このような自動化をしようと思ったのかですが、ルーチンワークをできるだけ自動化し、人間が介在しないと出来ない仕事に注力したかったからです。この情報が同様の考えを持つ方の参考になれば幸いです。