レコード一覧画面に時間の合計を表示したい

お世話になります。

ドローンの飛行履歴を記録するアプリを作成しています。
飛行時間が20時間に達する度に機体の点検が義務付けられているため、一覧画面に現在の飛行時間の合計を表示したいと考えています。

https://developer.cybozu.io/hc/ja/community/posts/360001961103-kintone-%E3%83%AC%E3%82%B3%E3%83%BC%E3%83%89%E4%B8%80%E8%A6%A7%E7%94%BB%E9%9D%A2-%E9%9B%86%E8%A8%88%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6

こちらの情報を参考にさせていただいたのですが、フィールドの値が数値でないためか「NaN」と表示されてしまいました。

「合計:○時間」 と表示させるにはどのようにしたらよいでしょうか。

ご教示のほど、よろしくお願いいたします。

こんばんは。

おそらくは時刻型(‘HH:MM’)で記録されているために数値として認識されないと思います。

一度Date型に置換してから時と分を取り出せばよいと思います。

 

>> return previousValue + Number(record.小計.value);

上記をフィールドコードを「飛行時間」と想定して書いてみます。

(小数点以下の丸めを行っていないので、必要であればreturnValue に対して加工してみてください)

kintone.app.getHeaderMenuSpaceElement().innerHTML = ‘合計:’ + event.records.reduce(function(previousValue, record){

    let thisTime = Date(‘1990-01-01T’ + (record[‘飛行時間’].value || ‘00:00’) + ‘+09:00’);

    let returnValue = previousValue + Number(thisTime.getHours() + (thisTime.getMinutes() / 60) );

    return returnValue ;

).toLocaleString():

 

のあまる様、ご返信ありがとうございます。
早速教えていただいた記述を試してみたのですが、一覧画面に何も表示されませんでした。
お恥ずかしながらJavaScriptを今回始めて触りまして、記述ルール等を理解しておりません。

大変申し訳ないのですが、下記の記述で誤っている箇所があればご指摘いただけないでしょうか。

 

(function() {
“use strict”;
var getRecords = function(app, tmpRecords){
var limit = 500;
var tmpRecords = tmpRecords || [];
return kintone.api(kintone.api.url(‘/k/v1/records’, true), ‘GET’, {
app: app,
query: ‘limit ’ + limit +’ offset ’ + tmpRecords.length
}).then(function(response){
tmpRecords = tmpRecords.concat(response.records);
return response.records.length === limit ? getRecords(app, tmpRecords) : tmpRecords;
});
}
kintone.events.on(‘app.record.index.show’, function(event){
getRecords(kintone.app.getId()).then(function(records){

kintone.app.getHeaderMenuSpaceElement().innerHTML = ‘合計:’ + event.records.reduce(function(previousValue, record){

    let thisTime = Date(‘1990-01-01T’ + (record[‘飛行時間’].value || ‘00:00’) + ‘+09:00’);

    let returnValue = previousValue + Number(thisTime.getHours() + (thisTime.getMinutes() / 60) );

    return returnValue ;

).toLocaleString():

});
});
})();

動作を見てみましたが、Array.prototype.reduceの仕様により、初回はpreviousValueに1行目のレコードオブジェクトが入ります。

そのため、代入前にpreviousValueのデータ型確認が必要となります。

'app.record.index.show’イベント配下のソースを次のものに置き換えてみてください。

(自身のテスト環境にて動作確認できました)

getRecords(kintone.app.getId()).then(function(records){
    kintone.app.getHeaderMenuSpaceElement().innerHTML = ‘合計:’ + parseInt(records.reduce(function(previousValue, record){
      let thisTime = new Date(‘1990-01-01T’ + (record[‘飛行時間’].value || ‘00:00’) + ‘+09:00’);
      let returnValue = parseInt(thisTime.getHours()) * 60 + parseInt(thisTime.getMinutes());
      if( typeof previousValue === ‘number’){
          returnValue += previousValue;
      }else{
          let priorTime = new Date(‘1990-01-01T’ + (previousValue[‘飛行時間’].value || ‘00:00’) + ‘+09:00’);
          returnValue += parseInt(priorTime.getHours()) * 60 + parseInt(priorTime.getMinutes());
      }
      return returnValue;
    }) /60 *100 )/100 + ‘時間’;
});
return event;

 

のあまる様、ご指摘と動作確認ありがとうございます。
‘app.record.index.show’イベント配下のソースを書き換えたのですが、’).toLocaleString():'の手前までで良かったでしょうか。

書き換え後のソースです。
まだ私の環境では表示されず、必要な記号等まで消してしまったのかもしれません。

 

(function() {
“use strict”;
var getRecords = function(app, tmpRecords){
var limit = 500;
var tmpRecords = tmpRecords || [];
return kintone.api(kintone.api.url(‘/k/v1/records’, true), ‘GET’, {
app: app,
query: ‘limit ’ + limit +’ offset ’ + tmpRecords.length
}).then(function(response){
tmpRecords = tmpRecords.concat(response.records);
return response.records.length === limit ? getRecords(app, tmpRecords) : tmpRecords;
});
}
kintone.events.on(‘app.record.index.show’, function(event){
getRecords(kintone.app.getId()).then(function(records){
kintone.app.getHeaderMenuSpaceElement().innerHTML = ‘合計:’ + parseInt(records.reduce(function(previousValue, record){
let thisTime = new Date(‘1990-01-01T’ + (record[‘飛行時間’].value || ‘00:00’) + ‘+09:00’);
let returnValue = parseInt(thisTime.getHours()) * 60 + parseInt(thisTime.getMinutes());
if( typeof previousValue === ‘number’){
returnValue += previousValue;
}else{
let priorTime = new Date(‘1990-01-01T’ + (previousValue[‘飛行時間’].value || ‘00:00’) + ‘+09:00’);
returnValue += parseInt(priorTime.getHours()) * 60 + parseInt(priorTime.getMinutes());
}
return returnValue;
}) /60 *100 )/100 + ‘時間’;
});
return event;

).toLocaleString():

});
});
})();

Mayuko Eguchi
ご提示したソースでは、parseInt(~.getHours())によって整数部分のみを抜き出して数値としています(Numberクラスでの出力は行っていません)。

また、文字列との結合を行ってた数字変数は文字として扱われ、代入されます。

数字部分の表記にブラウザのロケールを考慮する場合、下記のようになります。

getRecords(kintone.app.getId()).then(function(records){
    kintone.app.getHeaderMenuSpaceElement().innerHTML = '合計:' +**Number(**parseInt(records.reduce(function(previousValue, record){
      let thisTime = new Date('1990-01-01T' + (record['飛行時間'].value || '00:00') + '+09:00');
      let returnValue = parseInt(thisTime.getHours()) * 60 + parseInt(thisTime.getMinutes());
      if( typeof previousValue === 'number'){
          returnValue += previousValue;
      }else{
          let priorTime = new Date('1990-01-01T' + (previousValue['飛行時間'].value || '00:00') + '+09:00');
          returnValue += parseInt(priorTime.getHours()) * 60 + parseInt(priorTime.getMinutes());
      }
      return returnValue;
    }) /60 *100 )/100**).toLocaleString()**+ '時間';
});
return event;

のあまる様、度々のご回答本当にありがとうございます。
恥を承知で申し上げるのですが、どの記述が問題で何が動作に支障を来しているのかが全く理解できておりません。
最後にご回答いただいたソースに書き換えてアップしたのは下記の内容なのですが、まだ表示されませんでした。

(function() {
“use strict”;
var getRecords = function(app, tmpRecords){
var limit = 500;
var tmpRecords = tmpRecords || [];
return kintone.api(kintone.api.url(‘/k/v1/records’, true), ‘GET’, {
app: app,
query: ‘limit ’ + limit +’ offset ’ + tmpRecords.length
}).then(function(response){
tmpRecords = tmpRecords.concat(response.records);
return response.records.length === limit ? getRecords(app, tmpRecords) : tmpRecords;
});
}
kintone.events.on(‘app.record.index.show’, function(event){

getRecords(kintone.app.getId()).then(function(records){
kintone.app.getHeaderMenuSpaceElement().innerHTML = ‘合計:’ + Number(parseInt(records.reduce(function(previousValue, record){
let thisTime = new Date(‘1990-01-01T’ + (record[‘飛行時間’].value || ‘00:00’) + ‘+09:00’);
let returnValue = parseInt(thisTime.getHours()) * 60 + parseInt(thisTime.getMinutes());
if( typeof previousValue === ‘number’){
returnValue += previousValue;
}else{
let priorTime = new Date(‘1990-01-01T’ + (previousValue[‘飛行時間’].value || ‘00:00’) + ‘+09:00’);
returnValue += parseInt(priorTime.getHours()) * 60 + parseInt(priorTime.getMinutes());
}
return returnValue;
}) /60 *100 )/100).toLocaleString() + ‘時間’;
});
return event;

).toLocaleString():

});
});
})();

飛行時間の値として使っているフィールドは「計算」で、添付画像のような設定を行っています。
不躾なお願いで本当に申し訳ないのですが、JavaScriptファイルの1行目から最後の行までをご提示していただけないでしょうか。

この件が解決したら、JavaScriptをきちんと勉強しようと思います。

Mayuko Eguchi

ソースを確認いたしまいた。

拝見したソースの内、末尾に記載している箇所がございました。

return event;

).toLocaleString():

});
});

の部分を次のように置き換えてください。

});
return event;
});

 

 

 

補足です。

return event; は「kintone.events.on(‘app.record.index.show’, function(event){ ~ } 」部分の戻り値ととして必要となります。

(抜けてしまった場合、他のJavaScriptが動作しない要因となるのでお行儀的ないみで追記してください)

 

一方で、「getRecords(kintone.app.getId()).then(function(records){ ~ }」は上記処理とは非同期で処理が行われます。
(修正後の動作ではreturn event実行後にgetRecords内の処理が実行されると思います)

kintone.Promiseなどを用いない場合は、特にreturn を必要としません。

大変失礼しました。

上記ソースを再度実行してみましたが、レコード数が1だとreduceの戻り値がrecord型になるため、NaNとなってしまいます。

そのため、Array.reduceよりはArray.forEachを用いた方が良かったですね。

以下にソースを記載しますので、張りつけて使ってみてください。

(function() {
    "use strict";
// レコード検索
var getRecords = function(app, tmpRecords){
var limit = 500;
var tmpRecords = tmpRecords || [];
return kintone.api(kintone.api.url('/k/v1/records', true), 'GET', {
app: app,
query: 'limit ' + limit +' offset ' + tmpRecords.length
}).then(function(response){
tmpRecords = tmpRecords.concat(response.records);
return response.records.length === limit ? getRecords(app, tmpRecords) : tmpRecords;
});
};

// 時刻合算
let sumTimes = function(records){
let resultValue = 0;
// 各レコードから分数を抜き出し、合算する
records.forEach(function(record){
let retFE = 0;
if( (record['飛行時間'] || null) !== null ){
let thisTime = new Date('1990-01-01T' + (record['飛行時間'].value || '00:00') + '+09:00');
retFE = parseInt(thisTime.getHours()) * 60 + parseInt(thisTime.getMinutes());
}
resultValue += retFE;
});
// 分数を時間数に変換後、Number型に変換して返す
return new Number(parseInt(resultValue * 100 / 60)/100);
};

// 一覧表示イベント
kintone.events.on('app.record.index.show', function(event){
// 非同期でレコード検索→HeaderMenuSpaceElementに合算を(ロケールに対応した書式で)表示
getRecords(kintone.app.getId()).then(function(records){
kintone.app.getHeaderMenuSpaceElement().innerHTML = '合計:' + sumTimes(records).toLocaleString() + '時間';
});
// 受取ったeventは必ずreturnする
return event;
});
})();

 

のあまる様、ご指摘ありがとうございます。

ついに合計時間を表示させることができました!
やはり、});などの不要な記述が含まれていたようです。
本当に嬉しいです。これを機に、もっとJavaScriptを勉強したくなりました。

お忙しい中、度々ご教示いただき本当にありがとうございました。