ファイルパスの分解で躓く
「ファイルがあちこちのフォルダに複写されており、原本変更したときにどのフォルダに複写されているか確認する必要がある。なんとかならないか?」という問合せあり。
文書管理としてどうかとは思うが、そこは片目つぶって.netでツールを作ったのだが、途中ファイルパスから文字列抽出するところで躓いた。
こんなツール
①ファイルを指定→②検索したいフォルダのルートを指定→③当該ファイルが格納されているフォルダをリストで表示
一応、一括または指定したものに対して上書き複写できるようにはしたいが、まずはリスト表示まで。
仕様として…
ア)原本ファイルがあるフォルダについては、検索時もしくはリスト表示時に除外することにする。
イ)検索は基本的に前方一致とする(複写先ファイルで「……(1).xls」や「……コピー.xls」等が存在するため)。
ウ)パスにおいて、ファイル名のひとつ上の階層は機種名、更にひとつ上の階層は客先名なので、リストに「客先」「機種」のカラムを作成して表示する。
ファイル検索は「System.IO.Directory.EnumerateFiles」を使って実行。
参考URL
https://dobon.net/vb/dotnet/file/getfiles.html
https://www.atmarkit.co.jp/fdotnet/dotnettips/1018enumfiles/enumfiles.html
第一引数の検索対象フォルダの中から第二引数の文字列を含むファイルをすべて取得してくれるので、ここまではらくちん。
戻ってきた文字列配列を分解してDatatableに格納していけばよいだけ。
実際ローカルで単純にファイルのフルパスをテーブルに格納して表示させるテストではまったく問題なかった。
問題が起きたのはこのあと。
ネットワークフォルダから検索するテストをする直前に仕様ウを実装しようとしたのだが、ファイル名、機種、客先の分解をInstrRev(Path, "¥")←(「¥」のところは円マーク半角、以下同様)で単純に分解していくだけでは芸がないと、わざわざFunctionにしてしまったわけだ。
ファイル名ならInstrRev1回、機種なら2回、客先なら3回…引数にフルパス渡して、取り出したい文字列のタイプを指定して…取り出した文字列はFunction内で宣言しているRtnStr変数に格納し、Returnする……といった感じ。
すんなり巧くいくと思ってたら…。
客先も機種もファイル名も空っぽ。
デバッグで確認してみたらFunctionに渡されているフルパスの「¥」が「\」になっているっぽい(実際はそう見えてるだけなんだろうが…)。
Function内InstrRevの第二引数は「¥」。区切り文字が見つからず、RtnStrに文字列入れないままFunctionを抜けているんだろうか? と。
InstrRevの戻り値が「0」だったのでたぶんそういうことなんだろう。
Visual Studioのエディタでは「\」が入れられないので、CHR使ってみたりもしたんだが、InstrRevの戻り値は「0」のまま。
ちなみにFunction実装前にファイル名部分だけを取り出す処理をダイレクトに記述していたのだが、そのときはInstrRev(FilePath, "¥")できちんと分解できてたはず(Path.GetFileName()は使っていなかった)…。
Functionに引数としてフルパス渡すときに何か変化が起きているんだろうか?
で、Function使用をやめ、元プロシージャ内に直接コード記述してみると…。
おや? ちゃんとInstrRevが値を返してくる。
結果的にはプロシージャ内処理で求めている処理はできてしまったのだが、なんとも釈然としない。
ByValとかByRefは関係ないよね? それって元の値を変えてしまうかどうかだよね?
Sytem.IO.Directory.EnumerateFilesで取得した文字列配列をFor eachで分解して文字列変数に格納、そのままFunctionに渡しているだけなんだけどなぁ…。
まぁ、Functionさえ使わなければ巧くいっている(?)ので、この件突き詰めることはしないけれども…。
そういうことがあった…という覚書。