フィールドタイプによる条件分岐(一覧画面でCSVの書き出し、特定のフィールドタイプは処理をとばす)

背景・実現したいこと

お世話になります。一覧画面でボタンをクリックするとCSVのDLが出来るようにしたいと思っています。

取りこむフィールドはJS内で指定しています。

データ取りこみ時にエラーをなくすため、

半角の「,」「"」「'」を全角に置換するコードを入れてあります。

フィールドタイプが日付のフィールドを取得しようとすると、

エラーがでる事が分かりました。

日付のフィールドがあってもCSVがDLできるようにしたいです。

 

コンソールのエラーが43行目を示したので、

置換の部分でひっかかっているのかな?と思いました。

if文で、フィールドタイプが日付の場合は、置換処理をしないようにしたいのですが、

このあたりご教授いただければ幸いです。

 

 

エラー情報 (開発者ツールのコンソール)

 download.do?app=69&contentId=1389&jsType=DESKTOP&hash=d162612c13b304d33d91b7d3900c007d6214b670:47 Uncaught (in promise) TypeError: Cannot read properties of null (reading ‘replace’)
    at download.do?app=69&contentId=1389&jsType=DESKTOP&hash=d162612c13b304d33d91b7d3900c007d6214b670:47:59
    at Array.forEach (<anonymous>)
    at download.do?app=69&contentId=1389&jsType=DESKTOP&hash=d162612c13b304d33d91b7d3900c007d6214b670:38:32
    at Array.forEach (<anonymous>)
    at recordToCsvData (download.do?app=69&contentId=1389&jsType=DESKTOP&hash=d162612c13b304d33d91b7d3900c007d6214b670:37:29)
    at dlCsv (download.do?app=69&contentId=1389&jsType=DESKTOP&hash=d162612c13b304d33d91b7d3900c007d6214b670:83:76)

 

利用したソースコード

(function() {
    “use strict”;
    kintone.events.on(‘app.record.index.show’, function(event) {
        if (document.getElementById(‘my_index_button’) !== null) {
            return;
        }

        var myIndexButton = document.createElement(‘button’);
        myIndexButton.id = ‘my_index_button’;
        myIndexButton.innerText = ‘csv_テスト’;

        // ボタンクリック時の処理
        myIndexButton.onclick = function() {
            
            // 1.CSVファイル生成用
            const HEADER =[‘日付’];
            //CSVに出力したいフィールドのフィールドコード

            // CSVをダウンロード
            const dlCsv = async ()=>{
                //フィールド名からCSVの文字列データを作る
                const setHeaderData = () => {
                    let headerData = ‘’;
                    HEADER.forEach(h => {
                        headerData += h + ‘,’;
                    });
                    headerData += ‘\r’;
                    return headerData;
                };  

                //レコードからCSVの文字列データを作る
                const recordToCsvData = records => {
                    let rowData = ‘’;
                    records.forEach(r => {
                        HEADER.forEach(h => {

                            //記号全角から半角に置換
                            var str_han2zen; 
                            
                            //★ここでフィールドタイプ識別【日付】は置換処理しないようにしたい
                            
                            str_han2zen = r[h].value
                            var str_han2zen = str_han2zen.replace(/,/g, ‘,’);
                            var str_han2zen = str_han2zen.replace(/"/g, ‘”’);
                            var str_han2zen = str_han2zen.replace(/'/g, ‘’’);
                            

                            
                            //rowData += r[h].value + ‘,’;
                            rowData += ‘"’ + str_han2zen + ‘"’+ ‘,’;
                        });
                        rowData += ‘\r’;
                    });
                    return rowData;
                }; 

                //URLエンコード
                const createDataUriFromString = str => {
                    // 文字列を配列に変換
                    const array = str.split(‘’).map(s => s.charCodeAt());
                    // エンコード
                    const sjis_array = Encoding.convert(array, ‘SJIS’, ‘UNICODE’);
                    const uInt8List = new Uint8Array(sjis_array);
                    return uInt8List;
                };  

                //2. CSVにしたいレコードを取得する
                const param_get = {
                    app:kintone.app.getId(),
                    //query:‘出力フラグ != 1’, // 絞り込みたいときはクエリを書く"出力フラグ = 0" など
                };
                const obj_get = await kintone.api(‘/k/v1/records’,‘GET’,param_get);
                const targetRecords =obj_get.records;

                //3. レコード1件以上だったらCSV出力
                if (targetRecords.length > 0) {

                    //4. CSVにするテキストデータを作成
                    const str = createDataUriFromString( setHeaderData() + recordToCsvData(targetRecords));

                    //5. CSVファイル作成
                    const blob = new Blob([str], {type:“text/csv”});
                    const url = URL.createObjectURL(blob);

                    //6. ダウンロード処理
                    const a = document.createElement(“a”);
                    document.body.appendChild(a);
                    a.download = “dlcsv_1.csv”;//ここすきなファイル名に
                    a.href = url;
                    a.click();
                    a.remove();
                    URL.revokeObjectURL(url);

                    // // 出力フラグをONにするようなコードはこのへんに
                    // let param_records = [~,~, ~,~];
                    // const param_upd = {
                    //     app:kintone.app.getId(),
                    //     records:param_records,
                    // };
                    // const obj_put = await kintone.api(‘/k/v1/records’,‘PUT’,param_upd);
                }
            }

            dlCsv(“dlcsv_1.csv”, event.records);
            
        };

        kintone.app.getHeaderMenuSpaceElement().appendChild(myIndexButton);
    });
})();

 

日付ではなく、空白時にnull(文字ではないもの)となるフィールドに対してreplace(文字に対して実行するもの)を実行していることが原因かと思います(そのため、同様に値がない場合にnullとなる空白のドロップダウンでも同じことが起きるはずです)。

日付フィールド全てを除外するのであればフィールドのタイプを参照して

if (r[h].type != 'DATE') ...

と記載できますが、値の有無を条件に加えることで問題ないかと思います。

                        HEADER.forEach(h => {
                          var str_han2zen = ''; 

                          if (r[h].value) str_han2zen = r[h].value.replace(/,/g, ',').replace(/"/g, '”').replace(/'/g, '’');
                            rowData += '"' + str_han2zen + '"' + ',';
                        });

また、値が配列となるチェックボックスや複数選択に対してreplaceを実行してもエラーが発生するため、エラーの可能性を減らすのであれば

                        HEADER.forEach(h => {
                          var str_han2zen = ''; 

                          if (Array.isArray(r[h].value) && r[h].type != 'FILE') {
                              str_han2zen = String(r[h].value.join('好きな区切り文字'));
                          } else if (r[h].value && r[h].type != 'FILE') {
                              str_han2zen = r[h].value;
                            }

                            str_han2zen = str_han2zen.replace(/,/g, ',').replace(/"/g, '”').replace(/'/g, '’');
                            rowData += '"' + str_han2zen + '"' + ',';
                        });

としてもよいと思います。

早速ご回答いただきありがとうございます!

空白時にnull(文字ではないもの)となるフィールド、なるほど~。
他のフィールドタイプについてもエラーの可能性を減らすコードまで
ご提案頂き助かりました!

どちらのコードも問題なく動きました。
これで実装できそうです。
丁寧に解説いただきありがとうございました!