数値フィールドが空の場合、プリントクリエータで非表示にしたい

プログラミング初心者です。非常に基本的な質問ですみません。

見積書アプリを作成し、cstap社さんのプリントクリエイターを用いて帳票を作成しようとしています。(デモ版で機能を調査中)

N/Aが出力されるのはうれしくないので、「kintoneの追加API setFieldShown はテーブルの個別セルに対応していますか?」のスレにあったサンプルプログラムを試したところ、以下の課題が生じました。

ー 個数、単価になにも入力しなかった場合(空のはず)、プリントクリエイターで表示すると、単価と小計の欄が0となる。
ー 一方、個数は何も表示されず期待通りの動きをしている。

この課題に対処する方法はありますでしょうか?

プリントクリエータのおまじない以外、サンプルプログラム以外は何も記載していません。

よろしくお願いします。

Shibayama様
cstapの落合です。

再現する状態をやっと再現できました!
プリントクリエイターで以下の設定(桁区切り)を行っている要素は、値が数値に変換されるため空文字が0となるようです。
ELEMENT_STYLE->IS_NUMBER=1;
おそらく、単価と小計は桁区切りの設定があるのだと思います。

すこし面倒ですが、以下のようなことを行えばできるかと思います。
・単価と小計を文字列フィールドにする
・JavaScriptで単価と小計を桁区切りして保存
・桁区切りの値から計算できるように計算処理を修正
・プリントクリエイターの設定をELEMENT_STYLE->TABLE_TYPE=STRING;に変更

以上、参考になりますでしょうか?

落合様

回答ありがとうございました。
確かに桁区切りしておりました。

桁区切りを外しても、同様の現象になりましたが、
はずせばいいという問題ではないでしょうか?

また、
・JavaScriptで単価と小計を桁区切りして保存
・桁区切りの値から計算できるように計算処理を修正
のやり方がわからなかったので、
また別のスレを2つ立てさせていただいたほうがいいでしょうか?

それにしてもKintoneを用いてやりたいことをやるのは大変ですね。

cstap様では、こういったことをサポートしていただけるサービスはありますか?
これが本業ではないため、あまり時間を使えないので
コストに見合えばそれも検討したいです。

よろしくお願いします。

Shibayama様
桁区切りは、ELEMENT_STYLE->IS_NUMBER=0;で「設定しない」に設定してもらえますでしょうか?

>・JavaScriptで単価と小計を桁区切りして保存
・桁区切りの値から計算できるように計算処理を修正
のやり方がわからなかったので、
また別のスレを2つ立てさせていただいたほうがいいでしょうか?
このスレのままで良いですよ!
あとでサンプルを添付いたします!

>cstap様では、こういったことをサポートしていただけるサービスはありますか?
無償サポートというわけにはいきませんが、柔軟に対応させていただいております。
http://pc.kintoneapp.com/contact.htmlからお問い合わせいただければ、ヒアリングの上お見積りいたします!

以上、よろしくお願いいたします!

さきほど言っておりましたサンプルです。
ご参考ください。

/**
* テーブル:Table
* 単価:price(文字列フィールド)
* 個数:num(数値フィールド)
* 小計:sales(文字列フィールド)
*
* 総計:total(数値フィールド)
*/

(function () {
“use strict”;

function loadJS(src) {
  document.write('<script type="text/javascript" src="' + src + '"></script>');
}
// jQuery の JavaScript ファイル
loadJS("https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js");

// 数値→桁区切り
var numberFormat = function (num) {
  if (typeof num === 'number') {
    return num.toString().replace(/^\d+[^\.]/, function (t) {
      return t.replace(/([\d]+?)(?=(?:\d{3})+$)/g, function (t) {
        return t + ',';
      });
    });
  } else {
    return num;
  }
}

// 桁区切り→数値
var number = function (numberFormatStr) {
  if (typeof numberFormatStr === 'string') {
    return parseInt(numberFormatStr.replace(',', ''), 10);
  } else {
    return numberFormatStr;
  }
}

/**
 * 計算処理
 */
var myCalculate = function (record) {
  var table = record.Table.value;
  var total = 0;
  for (var i = 0, l = table.length; i < l; i++) {
    var row = table[i].value; // テーブルの1行
    // 小計を計算
    var price = number(row.price.value);
    var num = row.num.value;
    if (price && num) {
      var sales = price * num;
      row.sales.value = numberFormat(sales);
      total += sales;
    } else {
      // priceかnumが空の場合はnull
      row.sales.value = null;
    }
    row.price.value = numberFormat(price);
  }
  record.total.value = total;
};

// イベント
kintone.events.on(["app.record.edit.show", "app.record.create.show"], function (event) {
  // 編集時に計算するイベント
  $(document.body).on('change', "input[type='text']", function () {
    var record = kintone.app.record.get();
    myCalculate(record.record);
    kintone.app.record.set(record);
  });

  // 無理やりDOM操作で編集不可に
  $(document).on('click', '.add-row-image-gaia', function () {
    var ele = $('.value-139700').children(); // 小計のclass
    ele.addClass('disabled-cybozu');
    ele.children('input').attr('disabled', 'disabled');
  });

  // 無理やりDOM操作で行削除イベント
  $(document).on('click', '.remove-row-image-gaia', function () {
    var record = kintone.app.record.get();
    myCalculate(record.record);
    kintone.app.record.set(record);
  });

  return event;
});

// 計算する数値フィールドを編集不可にする
kintone.events.on(["app.record.edit.show", "app.record.create.show"], function (event) {
  var table = event.record.Table.value;
  for (var i = 0, l = table.length; i < l; i++) {
    table[i].value.sales.disabled = true;
  }
  event.record.total.disabled = true;

  return event;
});

// 登録、編集時の処理
kintone.events.on(["app.record.edit.submit", "app.record.create.submit"], function (event) {
  myCalculate(event.record);

  return event;
});

})();

落合様

早速サンプルをいただきありがとうございました。

試したところ1つだけ妙な挙動がありました。

例えば、個数1、単価に1000000といれると、
計算されて、1000となってしまいます。

値の入れ方が間違えておりますでしょうか?

よろしくお願いします

Shibayama様
すいません。
','の置換でミスってますね。。。
以下、修正版です。

/**
 * テーブル:Table
 * 単価:price(文字列フィールド)
 * 個数:num(数値フィールド)
 * 小計:sales(文字列フィールド)
 * 
 * 総計:total(数値フィールド)
 */

(function () {
  "use strict";

  function loadJS(src) {
    document.write('<script type="text/javascript" src="' + src + '"></script>');
  }
  // jQuery の JavaScript ファイル
  loadJS("https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js");

  // 数値→桁区切り
  var numberFormat = function (num) {
    if (typeof num === 'number') {
      return num.toString().replace(/^\d+[^\.]/, function (t) {
        return t.replace(/([\d]+?)(?=(?:\d{3})+$)/g, function (t) {
          return t + ',';
        });
      });
    } else {
      return num;
    }
  }

  // 桁区切り→数値
  var number = function (numberFormatStr) {
    if (typeof numberFormatStr === 'string') {
      return parseInt(numberFormatStr.replace(/,/g, ''), 10);
    } else {
      return numberFormatStr;
    }
  }

  /**
   * 計算処理
   */
  var myCalculate = function (record) {
    var table = record.Table.value;
    var total = 0;
    for (var i = 0, l = table.length; i < l; i++) {
      var row = table[i].value; // テーブルの1行
      // 小計を計算
      var price = number(row.price.value);
      var num = row.num.value;
      if (price && num) {
        var sales = price * num;
        row.sales.value = numberFormat(sales);
        total += sales;
      } else {
        // priceかnumが空の場合はnull
        row.sales.value = null;
      }
      row.price.value = numberFormat(price);
    }
    record.total.value = total;
  };

  // イベント
  kintone.events.on(["app.record.edit.show", "app.record.create.show"], function (event) {
    // 編集時に計算するイベント
    $(document.body).on('change', "input[type='text']", function () {
      var record = kintone.app.record.get();
      myCalculate(record.record);
      kintone.app.record.set(record);
    });

    // 無理やりDOM操作で編集不可に
    $(document).on('click', '.add-row-image-gaia', function () {
      var ele = $('.value-139700').children(); // 小計のclass
      ele.addClass('disabled-cybozu');
      ele.children('input').attr('disabled', 'disabled');
    });

    // 無理やりDOM操作で行削除イベント
    $(document).on('click', '.remove-row-image-gaia', function () {
      var record = kintone.app.record.get();
      myCalculate(record.record);
      kintone.app.record.set(record);
    });

    return event;
  });

  // 計算する数値フィールドを編集不可にする
  kintone.events.on(["app.record.edit.show", "app.record.create.show"], function (event) {
    var table = event.record.Table.value;
    for (var i = 0, l = table.length; i < l; i++) {
      table[i].value.sales.disabled = true;
    }
    event.record.total.disabled = true;

    return event;
  });

  // 登録、編集時の処理
  kintone.events.on(["app.record.edit.submit", "app.record.create.submit"], function (event) {
    myCalculate(event.record);

    return event;
  });
})();

落合様

ありがとうございました。
確認しました。

現状ではほぼ完ぺきです。

他にもいろいろなケースで入力し、検証してみようと思います。

ありがとうございました。

いえいえ(^^)
また、なにかありましたらご質問ください!

落合様

たびたびすみません。一つ出てきました。

単価にマイナスの値(値引き)を入れた場合にも桁区切りをつけることは可能でしょうか?

こんな感じでどうでしょう?

/**
 * テーブル:Table
 * 単価:price(文字列フィールド)
 * 個数:num(数値フィールド)
 * 小計:sales(文字列フィールド)
 * 
 * 総計:total(数値フィールド)
 */

(function () {
  "use strict";

  function loadJS(src) {
    document.write('<script type="text/javascript" src="' + src + '"></script>');
  }
  // jQuery の JavaScript ファイル
  loadJS("https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js");

  // 数値→桁区切り
  var numberFormat = function (num) {
    if (typeof num === 'number') {
      return new Intl.NumberFormat().format(num);
    } else {
      return num;
    }
  }

  // 桁区切り→数値
  var number = function (numberFormatStr) {
    if (typeof numberFormatStr === 'string') {
      return parseInt(numberFormatStr.replace(/,/g, ''), 10);
    } else {
      return numberFormatStr;
    }
  }

  /**
   * 計算処理
   */
  var myCalculate = function (record) {
    var table = record.Table.value;
    var total = 0;
    for (var i = 0, l = table.length; i < l; i++) {
      var row = table[i].value; // テーブルの1行
      // 小計を計算
      var price = number(row.price.value);
      var num = row.num.value;
      if (price && num) {
        var sales = price * num;
        row.sales.value = numberFormat(sales);
        total += sales;
      } else {
        // priceかnumが空の場合はnull
        row.sales.value = null;
      }
      row.price.value = numberFormat(price);
    }
    record.total.value = total;
  };

  // イベント
  kintone.events.on(["app.record.edit.show", "app.record.create.show"], function (event) {
    // 編集時に計算するイベント
    $(document.body).on('change', "input[type='text']", function () {
      var record = kintone.app.record.get();
      myCalculate(record.record);
      kintone.app.record.set(record);
    });

    // 無理やりDOM操作で編集不可に
    $(document).on('click', '.add-row-image-gaia', function () {
      var ele = $('.value-139700').children(); // 小計のclass
      ele.addClass('disabled-cybozu');
      ele.children('input').attr('disabled', 'disabled');
    });

    // 無理やりDOM操作で行削除イベント
    $(document).on('click', '.remove-row-image-gaia', function () {
      var record = kintone.app.record.get();
      myCalculate(record.record);
      kintone.app.record.set(record);
    });

    return event;
  });

  // 計算する数値フィールドを編集不可にする
  kintone.events.on(["app.record.edit.show", "app.record.create.show"], function (event) {
    var table = event.record.Table.value;
    for (var i = 0, l = table.length; i < l; i++) {
      table[i].value.sales.disabled = true;
    }
    event.record.total.disabled = true;

    return event;
  });

  // 登録、編集時の処理
  kintone.events.on(["app.record.edit.submit", "app.record.create.submit"], function (event) {
    myCalculate(event.record);

    return event;
  });
})();

落合様

ありがとうございます。
確認しました。
試用期間中に確認できてよかったです。

これで現時点でやりたいことはだいたいできました。

あと残っている課題としては、承認がとれた見積書のみ
帳票出力のボタンが出るようにする、ということですが、
これは次のステップでやろうと思います。

ありがとうございました。
お礼まで

Shibayama様
やりたいことが実現できたようで良かったです。
また何かありましたら、ご質問ください!