自習用コンテンツ その4(https://automate.sct.co.jp/knowledge/12049/)の内容は如何でしたでしょうか?
簡単に出来てしまった方も、難しかった方もいたかと思います。
下記では、解説を書いていきます。
(解答例のコードは、ページ最下部に書いています。)
■観点
今回のコンテンツでは、正規表現を用いたテキスト検索およびその際のループの使い方を観点としました。
固定文字列ではないが一定の法則・フォーマットで書かれている文字列をいかにして特定・取得できるかが今回のポイントになります。
■1. 必要な変数の用意
今回は、多くの変数が必要になります。なお、変数は必要だと感じた時点で随時追加作成する方式でも構いません。
なお、必ずしも「変数」である必要は無く、配列を使用しても構いません。
以下の役割を果たす変数をそれぞれ作成します。
・ファイルの内容(テキスト)を格納する変数
・条件に合致したテキストを抜き出した後、それを格納しておく変数
・条件に合致するテキストが何度出現するかを格納する変数
・メンテナンス日を格納する変数
・メンテナンス開始時間を格納する変数
・メンテナンス終了時間を格納する変数
・テキスト処理において、現在何番目のテキストを処理しているかを記録・格納する変数
・Excelに何行書いたかを記録・格納する変数
<AMVARIABLE NAME="var_FileContent" DESCRIPTION="ファイルのテキスト全体を格納する変数" />
<AMVARIABLE NAME="var_foundtext" DESCRIPTION="条件に合致したテキストを格納する変数" />
<AMVARIABLE NAME="var_total" DESCRIPTION="条件に合致するテキストの合計数(個数)を格納する変数" />
<AMVARIABLE NAME="var_MaintainDate" DESCRIPTION="メンテナンス日付" />
<AMVARIABLE NAME="var_MaintainStart" DESCRIPTION="メンテナンス開始時間" />
<AMVARIABLE NAME="var_MaintainEnd" DESCRIPTION="メンテナンス終了時間" />
<AMVARIABLE NAME="var_index_text" DESCRIPTION="現在処理中のテキストは何番目であるかを記録(カウント)する変数" />
<AMVARIABLE NAME="var_index_excel" VALUE="2" DESCRIPTION="Excelは2行目から記入するので、「2」から開始 1行書込むごとに1ずつ増やす" TYPE="number" />
■2. 書込み対象となるExcelを開く
変数定義の後、テキスト処理を実施する前にExcelを開きます。
今回操作する対象のExcelは1つだけで、かつテキスト処理中のループ内でExcelを開くと非常にややこしいので、最初に開きます。
<AMEXCEL SESSION="ExcelSession1" WORKBOOK="%GetDesktopDirectory()%\00009425\雛形.xlsx" />
■3. 処理対象となるファイルの一覧をデータセット化
今回処理対象となるとは、所定のフォルダ内に存在するテキストファイル(拡張子が「.txt」)です。
そのため、「ファイル システム - 情報の取得」アクションを使用し、テキストファイルに絞って情報取得を実施します。
(図1:「ファイル システム - 情報の取得」)
<AMFILESYSTEM ACTIVITY="get" SOURCE="%GetDesktopDirectory()%\00009425\*.txt" RESULTDATASET="ds_files" FILEPROPERTY="fullname" />
■4. テキストファイルを順繰りに処理する(=ループする)
手順3で作ったデータセット(ファイル一覧)をもとにループを行います。
--------------以下、「■4」のループ内における処理です--------------
■5. テキストファイルの内容を変数化
テキストファイルの内容を変数に格納するには、「ファイルシステム - ファイルからの読込み」アクションを使用します。
読み込み対象のファイル名はデータセット化しているため、「データセット名.FullName」でフルパスを取得して指定します。
<AMFILESYSTEM ACTIVITY="read_file" FILE="%ds_files.Fullname%" RESULTVARIABLE="var_FileContent" />
■6. メンテナンス日の書いてある部分のテキストを抽出する
メンテナンス日が書いてある部分は、必ず以下のようなフォーマットになっています。
括弧で括ってある部分は可変、それ以外は固定文字列です。
「・(数字)月(数字)日 (数字):(数字) ~ (数字):(数字)」
(上記のフォーマットは指定せず、「(数字)月(数字)日」だけを取得するなどしても、関係ない部分をひっぱってくるようテキストを作っています)
ここで、(数字)の部分は1桁にも2桁にもなりうるので、「任意の数字1文字以上」を表すことができるか否かがポイントになります。
以下、順に整理します
・6-1. 「数字一文字以上」を表す正規表現について
「数字1文字」であれば、「\d」または「[0-9]」のいずれかで指定できます。
また、「直前の文字が1文字以上」は、「+」で指定できます。
したがって、「数字一文字以上」は「\d+」または「[0-9]+」のいずれかで表現可能です。
ゆえに、当該フォーマットを表す正規表現は
「・\d+月\d+日 \d+:\d+ ~ \d+:\d+」
のようになります。
・6-2. メンテナンス日(=上記のフォーマット)が文中に何回現れるかを取得
このあと、メンテナンス日を1日ずつ記録する必要があるので、1つの文章に何回メンテナンス日が現れるかを把握する必要があります。
そのため、「総検出数を変数に設定する」の項目に所定の変数を設定します。
<AMTEXT TEXT="%var_FileContent%" FIND="・\d+月\d+日 \d+:\d+ ~ \d+:\d+" USERE="YES" TOTALMATCHESVARIABLE="var_total" />
■7. 「■6」で検出した個数分、ループ
メンテナンス日が書かれた部分が検出された回数だけ、情報抽出を実施する必要があります。
そのため、「1」から「%var_total%」までのループを定義します。
この際、「今、何個目のメンテナンス日を処理しているか」を取得する為、現在のインデックスを変数に格納するよう設定します。
xxxxxxxxxxxxxxxxxxx以下、「■7」のループ内における処理ですxxxxxxxxxxxxxxxxxxx
■8. メンテナンス日に該当する文字列を抽出する
「■6」と同様のフォーマットの指定方法で、実際の文字列を抽出します。
現在何回目のループであるか、および抽出したテキストを設定する変数をそれぞれ指定します。
<AMTEXT TEXT="%var_FileContent%" FIND="・\d+月\d+日 \d+:\d+ ~ \d+:\d+" USERE="YES" INDEX="%var_index_text%" FOUNDTEXTVARIABLE="var_foundtext" />
■9. 「■8.」の結果から、「メンテナンス日付」「メンテナンス開始時間」「メンテナンス終了時間」をそれぞれ抽出
欲しい要素は、それぞれ以下のような条件があります。
メンテナンス日付:必ず「\d+月\d+日」のフォーマットになっている
メンテナンス開始時間:「\d+:\d+」のフォーマットのうち、1回目に現れるもの
メンテナンス終了時間:「\d+:\d+」のフォーマットのうち、2回目に現れるもの
「メンテナンス日付」自体は、該当するフォーマットのテキストは1つしか現れないので取得が楽ですが、「メンテナンス開始時間」と「メンテナンス終了時間」はフォーマットが同じになっています。
一方、順番は決まっているので「次のインスタンスから開始する」の部分を「1」「2」と明示的に指定することで対応できます。
<AMTEXT TEXT="%var_foundtext%" FIND="\d+月\d+日" USERE="YES" FOUNDTEXTVARIABLE="var_MaintainDate" />
<AMTEXT TEXT="%var_foundtext%" FIND="\d+:\d+" USERE="YES" FOUNDTEXTVARIABLE="var_MaintainStart" />
<AMTEXT TEXT="%var_foundtext%" FIND="\d+:\d+" USERE="YES" INDEX="2" FOUNDTEXTVARIABLE="var_MaintainEnd" />
■10. 取得した「メンテナンス日」「メンテナンス開始時間」「メンテナンス終了時間」「情報の出所(ファイル名)」をExcelに書き込み
各種情報はそれぞれ1アクションずつで書き込んでも問題はありませんが、「リスト」を使用して書き込むことで1アクションで完結します。
<AMEXCEL ACTIVITY="set_cell" SESSION="ExcelSession1" SETTERTYPE="list" CELLROW="%var_index_excel%" CELLCOLUMN="1" LIST="%var_MaintainDate%,%var_MaintainStart%,%var_MaintainEnd%,%ds_files.Filename%" />
■11. Excelの書込み先を1行下に下げる
Excelの書込み先インデックスを1増やし、書込み先を1行下に下げます。
<AMVARIABLE ACTIVITY="increment" RESULTVARIABLE="var_index_excel" />
xxxxxxxxxxxxxxxxxxx以上、「■7」のループ内における処理ですxxxxxxxxxxxxxxxxxxx
--------------以上、「■4」のループ内における処理です--------------
■12. Excelを別名保存
本日日付を前につけた形で別名保存します。「/」はファイル名に使えないので、「format」関数で整形しています。
<AMEXCEL ACTIVITY="close_workbook" SESSION="ExcelSession1" SAVETYPE="save_as" DESTINATION="C:\TEMP\テキスト編集\%format(date(), "yyyymmdd")%_メンテ予定日.xlsx" />
今回定義する処理は以上になります。
(処理構築例:展開するにはここをクリック)
<AMVARIABLE NAME="var_FileContent" DESCRIPTION="ファイルのテキスト全体を格納する変数" VALUE="" />
<AMVARIABLE NAME="var_foundtext" DESCRIPTION="条件に合致したテキストを格納する変数" VALUE="" />
<AMVARIABLE NAME="var_total" DESCRIPTION="条件に合致するテキストの合計数(個数)を格納する変数" VALUE="" />
<AMVARIABLE NAME="var_MaintainDate" DESCRIPTION="メンテナンス日付" VALUE="" />
<AMVARIABLE NAME="var_MaintainStart" DESCRIPTION="メンテナンス開始時間" VALUE="" />
<AMVARIABLE NAME="var_MaintainEnd" DESCRIPTION="メンテナンス終了時間" VALUE="" />
<AMVARIABLE NAME="var_index_text" DESCRIPTION="現在処理中のテキストは何番目であるかを記録(カウント)する変数" VALUE="" />
<AMVARIABLE NAME="var_index_excel" VALUE="2" DESCRIPTION="Excelは2行目から記入するので、「2」から開始 1行書込むごとに1ずつ増やす" TYPE="number" />
<!--Excelを開く-->
<AMEXCEL SESSION="ExcelSession1" WORKBOOK="%GetDesktopDirectory()%\00009425\雛形.xlsx" />
<!--処理対象フォルダ内のExcelをデータセット化-->
<AMFILESYSTEM ACTIVITY="get" SOURCE="%GetDesktopDirectory()%\00009425\*.txt" RESULTDATASET="ds_files" FILEPROPERTY="fullname" />
<!--ファイルリストに従ってループ-->
<AMLOOP ACTIVITY="dataset" DATASET="ds_files" />
<!--ファイル内容を変数化-->
<AMFILESYSTEM ACTIVITY="read_file" FILE="%ds_files.Fullname%" RESULTVARIABLE="var_FileContent" />
<!--指定フォーマットのテキストが何回出現するか取得-->
<AMTEXT TEXT="%var_FileContent%" FIND="・\d+月\d+日 \d+:\d+ ~ \d+:\d+" USERE="YES" TOTALMATCHESVARIABLE="var_total" />
<!--メンテナンス日の出現回数分ループ-->
<AMLOOP FROM="1" TO="%var_total%" RESULTVARIABLE="var_index_text" />
<!--メンテナンス日の部分を取得し、それぞれの要素に分解-->
<AMTEXT TEXT="%var_FileContent%" FIND="・\d+月\d+日 \d+:\d+ ~ \d+:\d+" USERE="YES" INDEX="%var_index_text%" FOUNDTEXTVARIABLE="var_foundtext" />
<AMTEXT TEXT="%var_foundtext%" FIND="\d+月\d+日" USERE="YES" FOUNDTEXTVARIABLE="var_MaintainDate" />
<AMTEXT TEXT="%var_foundtext%" FIND="\d+:\d+" USERE="YES" FOUNDTEXTVARIABLE="var_MaintainStart" />
<AMTEXT TEXT="%var_foundtext%" FIND="\d+:\d+" USERE="YES" INDEX="2" FOUNDTEXTVARIABLE="var_MaintainEnd" />
<!--Excelに書き込み-->
<AMEXCEL ACTIVITY="set_cell" SESSION="ExcelSession1" SETTERTYPE="list" CELLROW="%var_index_excel%" CELLCOLUMN="1" LIST="%var_MaintainDate%,%var_MaintainStart%,%var_MaintainEnd%,%ds_files.Filename%" />
<AMVARIABLE ACTIVITY="increment" RESULTVARIABLE="var_index_excel" />
<AMLOOP ACTIVITY="end" />
<AMLOOP ACTIVITY="end" />
<AMEXCEL ACTIVITY="close_workbook" SESSION="ExcelSession1" SAVETYPE="save_as" DESTINATION="%GetDesktopDirectory()%\00009425\%format(date(), "yyyymmdd")%_メンテ予定日.xlsx" />