猫と一緒にガジェットライフ♪ムチャです。
以前gistで公開していたExcelファイル正規表現検索スクリプトですが、プログラマーのくせにGitHubリポジトリを作っていなかったので、新しく作ってそちらへ移しました。
ドヤ顔するつもりもなくて、「プログラマーのクセにまだリポジトリ作ってなかったのかよ!」という感じですが、ブログ書くのは飲み会と一緒できっかけは何でもいいのですw
最後にリンクを載せますが、「説明とか不要」という方はこちらからダウンロードしてください。
なにそれ?
特定のディレクトリにあるExcelファイルから、指定のキーワードを含むファイルを検索するスクリプトです。
セルだけでなく、オートシェイプ(図形内テキスト)、コメントも検索できます。
「そんなのツール使えばいいじゃん」
その通りです。有名なものに「RelaxTools Addin」があります。検索以外にも様々な機能を備えているので、使えるならばそちらを使いましょう。無料です。
じゃあそんなの要らないじゃんという話になるでしょうが、目的があるのです。
このスクリプトの目的
自由にソフトウェアを導入できない作業環境というのがあります。
自分はとある金融系の開発に携わっていたとき、開発環境はインターネットから隔離されていて外に出ることができず、当然勝手にソフトをインストールすることもできませんでした。
必要があれば申請して認められた場合のみ、開発環境に導入できました。
そのような現場ではドキュメントもMicrosoftOffice・・・特にExcelで作ったものが多いです。Officeなら何の疑いも無く導入されていますので。
大量のドキュメントがExcel作られるわけですが、それらを検索したい。しかし自由にソフトウェアを導入できない。
・・・そういう環境にいらっしゃる方へ、最悪プリントアウトしたコードを持っていって自分で打ち込んで使うことができるように・・・と考えて作ったものです。
(かつてアメリカが暗号化ソフトウェアの輸出を禁止していた時代に、禁止されているのは電子媒体だけだったので、印刷して国外へ持ち込んで輸出に成功したという話がありますが、それと同じですw)
プログラムは単独のテキストファイルで構成されていて、追加のライブラリやソフトウェアは不要です。(ただしOfficeが入っていないと動きません)
自分が経験したプロジェクトの中には、要件定義の時にユーザーが作成した既存業務フローが全てオートシェイプで作られていて、Excel標準のテキスト検索では全く検索ができないという状況がありました。元はこのオートシェイプ内テキストを検索するために作ったのですが、いろいろ手を加えてコメントも含む一通りの検索ができるようになっています。
大量のドキュメントがExcel作られるわけですが、それらを検索したい。しかし自由にソフトウェアを導入できない。
・・・そういう環境にいらっしゃる方へ、最悪プリントアウトしたコードを持っていって自分で打ち込んで使うことができるように・・・と考えて作ったものです。
(かつてアメリカが暗号化ソフトウェアの輸出を禁止していた時代に、禁止されているのは電子媒体だけだったので、印刷して国外へ持ち込んで輸出に成功したという話がありますが、それと同じですw)
プログラムは単独のテキストファイルで構成されていて、追加のライブラリやソフトウェアは不要です。(ただしOfficeが入っていないと動きません)
自分が経験したプロジェクトの中には、要件定義の時にユーザーが作成した既存業務フローが全てオートシェイプで作られていて、Excel標準のテキスト検索では全く検索ができないという状況がありました。元はこのオートシェイプ内テキストを検索するために作ったのですが、いろいろ手を加えてコメントも含む一通りの検索ができるようになっています。
使い方
コードはローカルディスク上にhtmlファイルとして保存して下さい。
ファイルをIE(Internet Explorer)で開きます。他のブラウザでは実行できません。
「このページのActiveXコントロールは安全出ない可能性があり~」という確認ダイアログが出ますが、情報を外部に送信したりしてないので安心して「はい」を選択して下さい。
※EMETを導入している場合は設定変更が必要かもしれません。後述します。
フォームにキーワード(正規表現可)とExcelファイルが置いてあるパスを入力します。サブフォルダも対象になります。
ネットワークドライブ上を指定すると時間がかかるので、必要なものだけを作業フォルダにコピーしてからそこを指定すると良いです。
オプションはお好みでどうぞ。
検索中は作業中のファイル名とプログレスバーが動きます。
途中キャンセルもできますが、仕様上シングルスレッドでシート単位に制御を返すようにしているので、ボタンをクリックしたら止まるまでお待ち下さい。
(今はWeb Workerとかありますが、ActiveXObjectがダメぽいので)
検索結果は順次テーブルに出力され、終わるとダイアログが出ます。
開くボタンを押すと、該当ファイルを読み取り専用で開いて、検索結果のシート→セル(オートシェイプの場合は図形の位置する左上のセル)を選択した状態にします。
Configuration→Appsを開いて、iexplore.exeのASRのチェックを外して下さい。
使用後は必ず元に戻しましょう。
「このページのActiveXコントロールは安全出ない可能性があり~」という確認ダイアログが出ますが、情報を外部に送信したりしてないので安心して「はい」を選択して下さい。
※EMETを導入している場合は設定変更が必要かもしれません。後述します。
フォームにキーワード(正規表現可)とExcelファイルが置いてあるパスを入力します。サブフォルダも対象になります。
ネットワークドライブ上を指定すると時間がかかるので、必要なものだけを作業フォルダにコピーしてからそこを指定すると良いです。
オプションはお好みでどうぞ。
検索中は作業中のファイル名とプログレスバーが動きます。
途中キャンセルもできますが、仕様上シングルスレッドでシート単位に制御を返すようにしているので、ボタンをクリックしたら止まるまでお待ち下さい。
(今はWeb Workerとかありますが、ActiveXObjectがダメぽいので)
検索結果は順次テーブルに出力され、終わるとダイアログが出ます。
開くボタンを押すと、該当ファイルを読み取り専用で開いて、検索結果のシート→セル(オートシェイプの場合は図形の位置する左上のセル)を選択した状態にします。
EMETを導入している場合
使用後は必ず元に戻しましょう。
コードの中身のお話し
プログラムに興味の無い方は読み飛ばしてください(;´∀`)VBじゃない理由
単に好きでは無いからw
new ActiveXObject("Excel.Application")
で生成したExcelのオブジェクトは、VBAのリファレンスにあるのと全く同じプロパティやメソッドを持っていて、基本的にはJavaScriptでも問題なく使えます。
で生成したExcelのオブジェクトは、VBAのリファレンスにあるのと全く同じプロパティやメソッドを持っていて、基本的にはJavaScriptでも問題なく使えます。
キャンセル受付
ActiveXを使っているのでマルチスレッドで動かせないため(多分・・・試してないw)、処理を小分けにしてsetTimeoutでブラウザに制御を返すようにしています。
シートが最小単位になっているので、巨大なシートを処理しているとなかなか返ってきません。セル・コメント・オートシェイプの処理まで分ければもっと細かくなるのですが、そこまでは手つかず・・・。
高速化
Excelのオブジェクトを操作すると遅いです。
初期のバージョンではRange#Findで検索した後FindNextで回していました。
この辺りの話は最初にリンクした過去記事にも載せていますが、基本的には全部一旦JavaScriptの配列にコピーしてそちらで操作する方が良いようです。
ただし、Range#Valueで2次元配列が取り出せるようなのですが、デバッガで見るとプロパティは見えるのに、参照するとundefinedになるという問題が分かりました。
これはVBArrayクラスでラップすることで解決できました。
初期のバージョンではRange#Findで検索した後FindNextで回していました。
この辺りの話は最初にリンクした過去記事にも載せていますが、基本的には全部一旦JavaScriptの配列にコピーしてそちらで操作する方が良いようです。
ただし、Range#Valueで2次元配列が取り出せるようなのですが、デバッガで見るとプロパティは見えるのに、参照するとundefinedになるという問題が分かりました。
これはVBArrayクラスでラップすることで解決できました。
var range = sheet.UsedRange; var vbrange = new VBArray(range.Value); for(var i = vbrange.lbound(1), xlen = vbrange.ubound(1); i < xlen; i++){ for(var j = vbrange.lbound(2), ylen = vbrange.ubound(2); j < ylen; j++){ var text = vbrange.getItem(i, j); : }
VBArrayはlbound(次元数)で最小値、ubound(次元数)で最大値が取れます。
以前はこの次にセル座標を得るためのCellオブジェクトを取得してからキーワード一致判定をしていたのですが、一致したときのみCellを取得すればいいのに今さら気付き(;´∀`)
変更したらセル検索がものすごく速くなりました。
以前はこの次にセル座標を得るためのCellオブジェクトを取得してからキーワード一致判定をしていたのですが、一致したときのみCellを取得すればいいのに今さら気付き(;´∀`)
変更したらセル検索がものすごく速くなりました。
セル検索の制限
セルは結合している場合があります。これを解除してやらないと検索がヒットしなかった記憶があります。
そのため解除する(読み取り専用にしているので大丈夫)のですが、ブックが共有状態だと解除できません。落ちてしまうんだったかな・・・?
Workbook#MultiUserEditingで判定しています。
また、リスト(テーブル)があると結合解除がうまくいきません。
先にリスト解除を行っています。
オートシェイプの検索
オートシェイプ(図形)も結合している場合があるので同様に解除します。
WorkSheet#Shapesでシート内の全オートシェイプを取得して、1つずつ処理します。
TypeプロパティはMsoShapeTypeという構造体?を返し、オートシェイプ(1) 、コールアウト(2)(ふき出し?)、テキストボックス(17)を対象にしています。
テキストを取得するにはTextFrame.Characters().Textで可能なのですが、たまに例外を吐くときがあって、どういうケースなのか追求し切れておらずtry~catchで逃げています(;´∀`)
コメントの検索
Worksheet#Commentsで取得したらあとは大体オートシェイプと同じ・・・ってこれ共通化できそうですね(;´∀`)
そのうちやります・・・。
デザイン
デザインセンス全く無いのですが、適当にCSSを組み込んでみました。
プログレスバーも。CSS消しても動作に影響ありません。
ダウンロード
以下からダウンロードしてください。ライセンスはMITライセンスとしました。
スクリプト集となっていますがまだ1つしかありません。
パワーがあったら他にも1ファイルで動くものを作ろうと思っています。
おしまいのひとこと
大したツールではないのですが、せっかく作ったのでGitHubにあげてみました。
金融系の仕事がほとんどだったので、いろいろ作ったものとかあるのですが持ち出すことができず、自分の作品というものがほとんどありません。
これからいろいろと作って公開していけたらいいなと思っています。
もしツールが役に立ったらブログコメントや各SNSで声をかけてもらえるととても喜びます。
とても役に立ったら欲しい物やAmazonギフトを贈っていただけるととても助かります(´Д⊂ヽ
それではみなさまよきガジェットライフを(´∀`)ノ
金融系の仕事がほとんどだったので、いろいろ作ったものとかあるのですが持ち出すことができず、自分の作品というものがほとんどありません。
これからいろいろと作って公開していけたらいいなと思っています。
もしツールが役に立ったらブログコメントや各SNSで声をかけてもらえるととても喜びます。
とても役に立ったら欲しい物やAmazonギフトを贈っていただけるととても助かります(´Д⊂ヽ
それではみなさまよきガジェットライフを(´∀`)ノ