本文へ移動
Wagby11
マニュアルのグループを選ぶ

WAGBY11 MANUAL / 10

関数と式の仕様

初期値と計算・導出項目で使える式の書き方、関数一覧、用途ごとの制約を説明します。

最終更新日:

計算・導出項目の小目次へ

1. このページで伝える機能

金額計算、条件分岐、文字列の組み立て、日付の移動などを、項目の値と関数の組み合わせで表現できます。初期値と計算・導出項目は、共通の式の文法と関数を使います。ただし、使う場面によって項目参照や休日関数などの制約が異なります。

式の構文を覚えてからAIに指示する必要はありません。「何から何を求めるか」「未入力ならどうするか」「いつ計算するか」を伝えると、AIが対応する式を組み立てられます。このページは、使える機能を確認するための資料です。

2. Wagby11で実現できること

例えば数量2と単価1,200から金額2,400を求め、条件に応じた割引や、表示用の文字列を組み合わせられます。

数量と単価から税抜金額2400円を計算した詳細画面
数量と単価を使って金額を求めた例です。

2.1 初期値・保存時計算・表示時計算の違い

使う場面値を求める時点・項目参照利用できる関数と主な制約
新規登録・更新の初期値フォーム初期化時。同じモデルの利用可能な項目を参照します。下記の関数を利用できます。入力変更では自動再評価しません。
コピー登録の初期値コピー後の値のスナップショットを参照します。別のコピー初期値が計算した結果は参照しません。
検索条件の初期値検索フォーム初期化時。ほかの項目の値は参照できません。日付・利用者・休日関数などは利用できます。項目を引数にする式は使えません。
保存時計算登録・更新の保存処理。同じモデルの項目から計算します。休日関数も利用できます。保存しない項目への依存は使えません。
表示時計算一覧・詳細などを返すときに計算します。休日関数は使えません。結果はDBへ保存せず、検索・並べ替えの条件にも使えません。

式はサーバーで評価します。初期値はフォームを開くときの候補であり、登録APIやアップロードなど、すべての登録経路へ値を設定する仕組みではありません。すべての保存経路で計算が必要なら保存時計算を使います。初期値の適用順序は式で初期値を求めるで説明します。

2.2 式の書き方

書ける内容式の例意味・注意点
項目・値quantity、3、3000000000L、"NORMAL"、true、null項目は同じモデルのname_enで指定します。大きな整数にはLを付けられます。
四則演算・余りquantity * unitPrice、125 % 60数値の+・−・×・÷と余り(+ - * / %)。例の余りは5です。括弧で順序を指定できます。
小数#decimal("0.1") + #decimal("0.2")小数は関数で明示します。結果は0.3です。0.1のような小数リテラルは使えません。
比較amount >= 10000、status == "DRAFT"==、!=、<、<=、>、>=。文字列も内容で比較します。
条件の組み合わせamount != null and amount > 10000and、or、!。andは左がfalse、orは左がtrueなら右を評価しません。
条件分岐member ? amount * #decimal("0.9") : amount条件 ? 成立時の値 : 不成立時の値。選ばれた側だけを評価します。
文字列連結#concatenate("見積:", subject)文字列の組み立てには#concatenateを使います。
関数の組み合わせ#moveDay(#today(), 7)内側の関数の結果を外側へ渡します。この例は今日の7日後です。

関数は#today()のように先頭に#を付け、項目はname_enをそのまま使います。関数名・項目名の大文字と小文字は区別します。式全体を#{...}や${...}で囲みません。YAMLでは#がコメント記号になるため、式文字列を引用符で囲みます。

式中の文字列は一重または二重引用符で囲みます。同じ引用符を文字として含める場合は二つ続けます。例:'O''Brien'。バックスラッシュで引用符を逃がす書き方は使いません。条件分岐の両側は、同じ型・null・共通の数値型にできる値を返すようにします。

2.3 使える関数の一覧

表のstringは文字列、integerは整数、numberは数値、decimalは十進小数、booleanは真偽値、date・time・datetimeは日付・時刻・日時です。[ ]は省略できる引数、...は複数の引数、->の右側は結果の型を表します。Tは同じ型同士、anyは式で扱えるスカラー値、|や/で並べた型はいずれか一つを意味します。

文字列・型変換 / 数値・丸め / 未設定値 / 日付・時刻・日時 / 利用者情報 / 休日・営業日

2.4 文字列・型変換

関数と引数・戻り値できること・主な規則
#concatenate(string...) -> string文字列を連結します。
#left(string [, integer]) -> string左端から文字列を取り出します。
#right(string [, integer]) -> string右端から文字列を取り出します。
#mid(string, integer [, integer]) -> string指定位置から文字列を取り出します。
#len(string) -> integer文字数を返します。
#trim(string) -> string前後と連続する空白を整理します。
#upper(string) -> string英字を大文字へ変換します。
#lower(string) -> string英字を小文字へ変換します。
#replace(string, string, string) -> stringリテラルの全置換。第1引数nullはnull。第2・3引数null、第2引数空文字はエラー
#padLeft(string, integer, string) -> stringコードポイント単位で左を1文字の埋め文字で補う。元の文字列が指定桁数以上ならそのまま。負数・不正な埋め文字はエラー
#plainText(string) -> stringstring。HTMLをサニタイズしてプレーンテキスト化。段落・改行・リストの区切りは改行で保持。HTMLエンティティは復号し、装飾・画像は出力しない。nullはnull
#toStr(any) -> string式のスカラーを文字列化。nullはnull。数値は桁区切り・指数なし、decimalの末尾0を保持。booleanはtrue/false
#text(date/time/datetime/number, string) -> stringJavaのDateTimeFormatter/DecimalFormatパターンで書式化。null引数はnull。environmentのlocale・timezoneを使用

#concatenateは1〜32個の文字列を連結し、nullと空文字を読み飛ばします。数値をつなぐときは#toStrや#textで文字列にします。#left・#rightの文字数省略時は1文字、#midの開始位置は1からです。文字数はUnicodeのコードポイント単位で数えます。

#trimは半角・全角空白、タブ、改行の前後を除去し、内部で連続する空白を半角空白一つにします。#textの日付書式はJavaのDateTimeFormatter、数値書式はDecimalFormatのパターンです。例:#text(amount, "#,##0.00")。文字列出力と#padLeftの指定桁数は最大65,536コードポイントです。

#toStrの日付はyyyy-MM-dd、時刻はHH:mm:ss、日時はyyyy-MM-dd'T'HH:mm:ssXXXの形式です。時刻・日時の秒未満は出力せず、日時の文字列化には評価時のタイムゾーンを使います。

2.5 数値・丸め

関数と引数・戻り値できること・主な規則
#decimal(string) -> decimal整数部38桁・小数部18桁以内の十進文字列。指数表記不可
#divide(number, number, integer [, string]) -> decimal指定桁数で除算。既定の丸めはHALF_UP
#abs(number) -> number絶対値を返します。
#round(number, integer) -> number指定桁で四捨五入します。
#roundDown(number, integer) -> number指定桁で0方向へ切り捨てます。
#roundUp(number, integer) -> number指定桁で0から離れる方向へ切り上げます。
#min(number...) -> number最小値を返します。
#max(number...) -> number最大値を返します。
#toLong(string/number) -> integerinteger。null・空文字はnull。文字列は符号付き十進整数のみ(空白・指数・小数表記不可)。数値の小数部が0でない場合や範囲外はエラー

#roundは四捨五入(HALF_UP)、#roundDownは0方向への切り捨て、#roundUpは0から離れる方向への切り上げです。残す小数桁数は−38〜38で、0は整数、負数は整数部分の桁を表します。例:#round(#decimal('2.15'), 1)は2.2です。

#divideの丸め方式は省略するとHALF_UPです。第4引数には'UP'・'DOWN'・'CEILING'・'FLOOR'・'HALF_UP'・'HALF_DOWN'・'HALF_EVEN'・'UNNECESSARY'を指定できます。#min・#maxは2〜32個の数値を取り、nullを含むとnullを返します。

2.6 未設定値の判定・補完

関数と引数・戻り値できること・主な規則
#isBlank(string) -> booleannull・空文字・空白だけの文字列ならtrueを返します。数値・日時の判定には使いません。
#nz(number) -> numbernullなら引数の静的な数値型の0、それ以外は同型の値。#nz(null)は禁止
#nvl(T, T) -> T第1引数がnullなら第2引数。同型だけ許可し、nullリテラルは他方から推論。両方nullは禁止

数値や日付の未設定はamount == nullのように判定します。#nz(quantity)は数値項目が未設定なら0にします。#nvl(name, "未入力")は未設定なら代わりの値を返します。#nz(null)や#nvl(null, null)は型を決められないため使えません。

関数の引数は先に評価されるため、#nvlでゼロ除算などのエラーを回避することはできません。危険な計算を避ける場合は、quantity == null or quantity == 0 ? null : #divide(amount, quantity, 2)のように条件分岐を使います。

2.7 日付・時刻・日時

関数と引数・戻り値できること・主な規則
#today() -> date評価基準時刻の日付を返します。
#now() -> datetime評価基準時刻の日時を返します。
#date(string) -> dateyyyy-MM-dd形式の文字列を日付に変換します。不正な形式・存在しない日付・nullはエラーです。
#betweenTime(time|datetime|string, 同じ型) -> time二つの値の時間差を返します。
#boMonth(date [, integer]) -> date指定月の月初日を返します。
#eoMonth(date [, integer]) -> date指定月の月末日を返します。
#dateDif(date, date, string) -> integer二つの日付の差を指定単位で返します。
#dateTimeValue(string [, string]) -> datetime文字列を日時へ変換します。
#dateValue(string) -> date文字列を日付へ変換します。
#eDate(date, integer) -> date指定月数だけ移動します。
#fiscalYear(date) -> integer4月始まりの年度を返します。
#hour(time|datetime) -> integer時を返します。
#minute(time|datetime) -> integer分を返します。
#second(time|datetime) -> integer秒を返します。
#moveDay(date, integer) -> date指定日数だけ移動します。
#moveHour(datetime, integer) -> datetime指定時間だけ移動します。
#moveMinute(datetime, integer) -> datetime指定分だけ移動します。
#moveSecond(datetime, integer) -> datetime指定秒だけ移動します。
#moveMonth(date, integer) -> date指定月数だけ移動します。
#moveYear(date, integer) -> date指定年数だけ移動します。
#timeValue(string) -> time文字列を時刻へ変換します。
#toDate(datetime) -> date日時を日付へ変換します。
#toDateTime(date|time|string) -> datetime値を日時へ変換します。
#toTime(datetime) -> time日時を時刻へ変換します。
#year(date|datetime) -> integer年を返します。
#month(date|datetime) -> integer月を1から12で返します。
#day(date|datetime) -> integer日を1から31で返します。
#weekDay(date [, integer]) -> integer曜日に対応する数値を返します。

#today()・#now()は処理ごとの基準時刻とenvironment.timezoneを使います。同じ処理内では基準時刻を共有します。日時から年月日などを取り出す場合は、その日時が持つオフセットを使い、別の地域へ暗黙に換算しません。

#boMonth・#eoMonthの第2引数は移動する月数で、省略時は0(同じ月)です。日付や日時の移動関数では、正数は未来、負数は過去へ移動します。

#dateDifの単位は'Y'(完了した年数)、'M'(完了した月数)、'D'(日数)、'YM'(年数を除く月数)、'YD'(年数を除く日数)、'MD'(月数を除く日数)です。終了日が開始日より前の場合はエラーです。#fiscalYearは4月始まりの年度を返します。

#moveMonth・#eDate・#moveYearは、移動先に同じ日がなければ月末へ補正します。#betweenTimeは差の絶対値を使い、24時間を超える日数部分を捨てます。長い期間の日数は#dateDifで求めます。

#dateTimeValueは既定でyyyy-MM-dd HH:mm:ssとyyyy/MM/dd HH:mm:ssを受け付け、任意の第2引数で書式を指定できます。#dateValueはyyyy-MM-ddとyyyy/MM/dd、#timeValueはHH:mmとHH:mm:ssを受け付けます。時刻は'9:5'などの1桁表記も使えます。

#weekDayの第2引数は、省略または1なら日曜1〜土曜7、2なら月曜1〜日曜7、3なら月曜0〜日曜6です。#toDateTime(date)はその日の0時、#toDateTime(time)は1970年1月1日のその時刻になります。

2.8 利用者情報

関数と引数・戻り値できること・主な規則
#userId() -> stringログイン者のjuser.user_idを返します。
#userName() -> stringログイン者のjuser.user_nameを返します。
#userEmail() -> stringstring。認証側で取得したjuser.email。未設定・利用者なしはnull
#hasGroup(string) -> booleanboolean。直接所属group_idsに完全一致するIDがあればtrue。未所属・利用者なし・null・空文字はfalse

利用者情報は処理に渡された認証情報のスナップショットです。利用者なしの処理ではID・名前・メールはnull、#hasGroupはfalseになります。#hasGroupは直接所属するグループIDとの完全一致であり、子孫グループやロール・権限の判定ではありません。

2.9 休日・営業日

関数と引数・戻り値できること・主な規則
#workday(date, integer) -> datedate。開始日を含めず営業日数だけ前後へ移動。0は開始日
#networkDays(date, date) -> integerinteger。両端を含む営業日数。逆順なら入れ替えた件数の負数
#isHoliday(date) -> booleanboolean。土日・公式休日・組織休日ならtrue

初期値と保存時計算で利用できます。表示時計算では使えません。休日サービスと辞書の構成が必要です。#workdayは開始日を含めず営業日数だけ移動し、0なら開始日を返します。#networkDaysは両端を含み、逆順なら負数を返します。

一度に扱える営業日数・走査日数・期間は最大3,660日です。処理全体にも評価回数の制限があります。保証期間外の不明な平日や上限超過はエラーとなり、暦日計算に置き換えることはありません。

2.10 式に書けないことと上限

  • 参照できるのは、用途で許可された同じモデルのスカラー項目や単一参照キーです。customer.nameのように参照先の項目を直接たどる記法や、配列・複数参照・関連データの操作は使えません。参照先の値はルックアップで用意します。
  • Javaのメソッド呼び出し、オブジェクト生成、代入、任意のDB・ファイル・ネットワーク操作は使えません。関数は一覧にあるものを使います。
  • IF(...)・AND(...)・TODAY()の形式は使いません。条件分岐は条件 ? 値1 : 値2、現在日は#today()です。小数リテラル、指数演算、正規表現、Elvis演算子も使えません。
  • 式は最大1,024文字、括弧などの深さは最大16段、関数の引数は最大32個です。式全体の構造やトークン数にも上限があり、複雑すぎる式は生成前の検証でエラーになります。

    複雑な計算や、式の上限を超える処理は、AppSchemaのrulesに「いつ・どの条件で・何を計算するか」を文章で記述し、その内容をもとにAIにJavaコードを実装させることで対応できます。ルールの説明文と、対応するJavaコードの実装・動作確認を合わせてAIに依頼します。

  • 自己参照と循環参照は使えません。式の結果は設定先の型に合う必要があり、整数への変換時は範囲と小数部も検査します。呼び出されない条件分岐の中も、関数名・型などは検証します。

通常の関数はnullを渡すとnullを返しますが、例外があります。例えば#len(null)は0、#isBlank(null)はtrueです。#decimal(null)・#date(null)はエラーです。関数ごとの規則を確認します。

アプリケーション全体の標準ロケールとタイムゾーンは、「環境」の標準の言語とタイムゾーンを設定するを参照してください。

3. AIへの指示例

最小限の指示例

数量と単価から金額を求め、円未満の扱いと未入力時の動作も提案してください。保存する金額と、表示用の文字列を分けてください。

対象項目、数値の桁数、丸め桁数、未入力時の扱いなどをAIが類推して補います。保存する値か表示だけの値か、四捨五入か切り捨てかなど、決まっている条件は具体的に伝えます。

より詳細な指示例

計算見積CalcQuoteで、quantityとunitPriceの積を小数第2位まで四捨五入し、amountへ登録・更新時に保存してください。
数量か単価が未入力の場合はamountをnullにします。amountはdecimal型、precision14・scale2とし、利用者には直接入力させません。
表示用のamountLabelはDBへ保存せず、amountが未設定なら「未入力」、設定済みなら「見積金額:2,400.00円」の形式にしてください。
Wagby11で使える関数と式の仕様を確認し、保存時計算と表示時計算を使い分けてください。quantity=2、unitPrice=1200と、片方が未入力の場合の結果を確認してください。
既存のモデル・主キー・項目・データ・権限を保持してください。必要なメニュー・一般利用者向け操作マニュアルを更新し、設計情報の検証・コード生成・起動後に保存結果と画面表示を確認してください。

4. 編集されるAppSchemaの例

数量と単価は定義済みとし、計算項目の抜粋を示します。利用者が構文を覚える必要はありません。

entity:
  attributes:
    - name: 金額
      name_en: amount
      type: decimal
      precision: 14
      scale: 2
      calc:
        on: [create, update]
        expression: 'quantity == null or unitPrice == null ? null : #round(quantity * unitPrice, 2)'
    - name: 金額表示
      name_en: amountLabel
      type: string
      length: 100
      transient: true
      calc:
        on: [display]
        expression: 'amount == null ? "未入力" : #concatenate("見積金額:", #text(amount, "#,##0.00"), "円")'

保存時計算の金額を表示時計算が読み、文字列へ整えます。計算項目は読み取り専用になります。文字列を作る目的と金額を保存する目的を分けて指示できます。

5. 参考資料

reference:式言語
designer/docs/appschema/html/reference/16-expression-language.html
reference:利用できる関数
designer/docs/appschema/html/reference/17-expression-functions.html
reference:rules(業務ルール)
designer/docs/appschema/html/reference/08-rules.html
guide:初期値
designer/docs/appschema/html/guide/05-input-control/01-initial-value.html