概要
サーバスクリプトでのファイル操作機能を使ってファイル出力、ファイル取込のバッチ処理を作成します。
ファイル操作用オブジェクト:$ps.file
ver1.4.12.0から利用できるようになったファイル操作用オブジェクト$ps.fileを使うと、Webサーバ上のファイルとディレクトリを操作することができます。
この機能を使うことでプリザンターからのファイル出力、プリザンターへのファイル取込を自動化(バッチ処理)することができます。
要件
以下のような構成にてCSVファイルの出力、読み込みを自動化することを要件とします。
要件1:ファイル出力
- 対象月、事業所区分、電気代、ガス代、水道代等の項目を持つ「光熱費」テーブルから今月のレコードをCSV出力する
- CSVのファイルレイアウトはID、事業所、電気代、ガス代、水道代、合計金額、対象月とする
- ファイルはWebサーバ上の所定のフォルダ(送信フォルダ)に出力する
- 出力前の時点で送信フォルダ上にあるファイルはバックアップ用フォルダに移動する
- 以上の出力処理を毎日定時刻に実行する
要件2:ファイル取込
- 取込先のテーブルは「光熱費」テーブルとする
- 取込対象のファイルは外部システムがWebサーバ上の所定のフォルダ(受信フォルダ)に保存しておくものとする
- 受信フォルダにあるファイルすべてを光熱費テーブルに追記でインポートする
- インポート完了後、受信フォルダのファイルすべてをバックアップ用フォルダに移動する
- 以上の取込処理を毎日定時刻に実行する
いざ実装!
要件に「毎日定時刻」とありますので、バックグラウンドサーバスクリプトを利用します。
また、サーバスクリプトでのファイル操作になりますので、$ps.fileを使ってファイル操作を行う処理を実装します。
ということで、実装した処理について説明します。
とその前に・・・
$ps.fileを利用するには「基準ディレクトリ」と「セクション」を定義する必要があります。この2つの用語の詳細はプリザンターオンラインマニュアルを参照してください。今回の処理実装にあたっては下図のように設定しました。
実装1:ファイル出力
それではファイル出力の処理の説明です。
// 処理日時の文字列取得:ファイル名用
getDateTimeString = function () {
return new Date().toLocaleString('ja-JP', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false, // 24時間表示
}).replaceAll('/', '').replaceAll(':', '').replaceAll(' ', '');
}
const section = 'fileCooperation';
const site = items.GetClosestSite('光熱費');
if (!site) {
logs.LogException('サイト:光熱費が見つかりません。');
return false;
}
// 送信フォルダにあるファイルをバックアップフォルダに移動
const lists = $ps.file.getFileList(section, 'send');
if (lists.length > 0) {
for (const element of lists) {
const moveResult = $ps.file.moveFile(section, `send/${element}`, `backup/send/${element}`);
if (!moveResult) {
logs.LogException(`ファイル移動失敗 ファイル名:${element}`);
return false;
} else {
logs.LogInfo(`ファイル移動成功 ファイル名:${element}`);
}
}
}
// ファイルエクスポート:エクスポート定義のID:1を使用。対象レコードは「対象月が今月」のレコード
siteId = site.SiteId;
const param = {
ExportId: 1,
View: {
ColumnFilterHash: {
DateA: "[\"ThisMonth\"]"
}
}
};
const path = `send/utilities${getDateTimeString()}.csv`;
const exportResult = $ps.file.export(section, path, siteId, $ps.JSON.stringify(param));
if (!exportResult) {
logs.LogException(`エクスポートに失敗しました。 ファイル名:${element}`);
return false;
} else {
logs.LogInfo(`エクスポート成功 ファイル名:${element}`);
}
解説
1~12行目は処理日時を文字列に変換する関数です。出力ファイルのファイル名に利用します。
15~19行目は対象テーブルを検索し、見つからなければlogsオブジェクトでエラーログを記録し、処理終了とします。18行目でreturn false;
としていますが、サーバスクリプトの登録で「関数化」にチェックをいれることで、任意のタイミングで処理を終了させることができます。「関数化」にチェックを入れないと処理実行時にエラーが発生します。(操作ログのErrMessageに「SyntaxError: Illegal return statement」と記録されます)
20~32行目は送信フォルダにあるファイルをバックアップフォルダ(送信)に移動する処理です。$ps.file.getFileListと$ps.file.moveFileでそれぞれpathに設定するフォルダやファイルに注意してください。21行目の$ps.file.getFileListはpathにフォルダを指定、24行目の$ps.file.moveFileでは移動元、移動先として"フォルダ\ファイル名"の形式でファイルパスを指定します。移動結果はlogsオブジェクトで処理結果を記録します。エラー時は27行目の通りreturn false;
で処理を終了させます。
33~50行目は$ps.file.exportにて対象テーブルからレコードをエクスポートし、送信フォルダに保存します。33~42行目はエクスポートする際の条件を記述しています。ExportId
は「テーブルの管理」-「エクスポート」で登録したIDを設定することで出力ファイルのフォーマットを指定します。
またViewでは出力する対象レコードの抽出条件を指定します。今回は対象月(DateA)が「今月」であるため、ColumnFilterHash
にDateA: "[\"ThisMonth\"]"
と指定しました。
ファイル出力結果はlogsオブジェクトで処理結果を記録します。エラー時は47行目の通りreturn false;
で処理を終了させます。
処理結果
実際に実行した結果は以下の通りとなります。
まずは対象テーブルである「光熱費」テーブルの初期状態として以下のように12件レコードが登録されており、そのうち3件が今月(2025年7月)のレコードです。
また、送信フォルダには先月分のファイルが保存されている状態とします。
本来はバックグラウンドサーバスクリプトのスケジュールを設定し、定時刻での実行としますが、今回は「テナントの管理」-「サーバスクリプト」から「ファイル出力」を選択し、「今すぐ実行」をクリックします。
処理実行後、送信フォルダにファイルが出力されたことが確認できます。ファイルの内容は指定した通り、今月分のレコード3件が出力されていることが確認できます。また先月分のファイルはバックアップフォルダ(送信)に移動していることも確認できます。
以上の通り、要件に沿った処理が実装できました。$ps.fileを使う事でファイル出力に関する処理をバッチ化することが可能となります。
次にファイル取込について説明します。
実装2:ファイル取込
const section = 'fileCooperation';
const site = items.GetClosestSite('光熱費');
if (!site) {
logs.LogException('サイト:光熱費が見つかりません。');
return false;
}
// 受信フォルダのファイルを読み込み、インポートする
siteId = site.SiteId;
const param = {};
const lists = $ps.file.getFileList(section, 'received');
if (lists.length > 0) {
for (const element of lists) {
const result = $ps.file.import(section, `received/${element}`, siteId, $ps.JSON.stringify(param));
if (!result) {
logs.LogException(`インポートに失敗しました。 ファイル名:${element}`);
return false;
} else {
logs.LogInfo(`インポート成功 ファイル名:${element} 結果:${$ps.JSON.stringify(result)}`);
}
}
// インポート完了後、ファイルをバックアップファイルに移動
for (const element of lists) {
const moveResult = $ps.file.moveFile(section, `received/${element}`, `backup/received/${element}`);
if (!moveResult) {
logs.LogException(`ファイル移動失敗 ファイル名:${element}`);
return false;
} else {
logs.LogInfo(`ファイル移動成功 ファイル名:${element}`);
}
}
}
解説
2~6行目は対象テーブルを検索し、見つからなければlogsオブジェクトでエラーログを記録し、5行目の通りreturn false;
で処理を終了させます。
11行目は$ps.file.getFileListで受信フォルダにある取込対象ファイルを取得します。ファイルがあれば13~30行目のファイル取込・移動処理を実行します。
12~20行目は$ps.file.importにて対象ファイルを取込みます。今回はすべて追記としますので、パラメータは指定しません(9行目)が、upsertする場合はパラメータに「UpdatableImport:true」を指定のうえ、「Key」にキー項目とするカラム名を設定してください。詳細はプリザンターオンラインマニュアルを参照ください。
取込結果はlogsオブジェクトで処理結果を記録します。エラー時は16行目の通りreturn false;
で処理を終了させます。
21~30行目は$ps.file.moveFileにて受信フォルダにあるファイルをバックアップフォルダ(受信)に移動します。移動結果はlogsオブジェクトで処理結果を記録します。エラー時は26行目の通りreturn false;
で処理を終了させます。
処理結果
実際に実行した結果は以下の通りとなります。
まずは対象テーブルである「光熱費」テーブルの初期状態として以下のように12件レコードが登録されています。
また、受信フォルダにはファイルが2つ保存されており、それぞれのファイルにはレコードが2件、1件記録されています。
ファイル出力の場合と同様に「テナントの管理」-「サーバスクリプト」から「ファイル取込」を選択し、「今すぐ実行」をクリックします。
処理実行後、光熱費テーブルへ取り込んだファイルに記載された計3件のレコードが追記されたことを確認できます。また、取り込んだファイルはバックアップフォルダ(受信)に移動していることも確認できます。
まとめ
$ps.fileを使ったファイル出力、取込の処理を作成しました。バックグラウンドサーバスクリプトを利用することで、いわゆるバッチ処理がプリザンターだけで作成できるようになります。外部の他システムとファイルベースで情報連携するような場合に今回のようなサンプルが利用できると思います。
最後に
プリザンターはユーザ皆様のやりたいことが実現できるツールです。サーバスクリプトをはじめとした強力なカスタマイズ機能がありますので、ユーザ要件に合わせた機能を開発することができます。
引き続きプリザンターをよろしくお願いします。