質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.70%

【JavaScript】複雑なCSVファイルのデータをselectboxの値に設定したい

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 918

ayaayape

score 6

前提・実現したいこと 
以下のようなCSVファイルのデータを、selextboxの値に設定したいです。

csvファイル
ーーーーーーーーーーーーーーーーーーー
|年|月|日|
|2019年|1月|1日|
|2019年|1月|2日|
|2019年|1月|3日|
|2019年|1月|4日|
|2019年|1月|5日|
|2019年|1月|6日|
|2019年|1月|7日|
空白行
|2018年|2月|1日|
|2018年|2月|2日|
|2018年|2月|3日|
|2018年|2月|4日|
ーーーーーーーーーーーーーーーーーーー

selectbox1に2019年,2018年
selectbox2に1月,2月
selectbox3に1日,2日…,7日
と表示され、かつ、selectbox同士データを紐づけたいと考えています。
(2019年を選択すると、1月7日まで表示される)

現段階で、CSVファイルの読み取りたい値の取得ができていません。
上記のCSVファイルで、
①,1列目(年)は、2019年を取得し、空白行があった次の行の2018年を取得する。
②,2列目(月)は、1月を取得し、空白行があった次の行の2月を取得する。
③,3列目(日)は、空白行があるまで、値を取得する。(1日から7日まで)
としたいのですが、①~③の記述の仕方が分からず、進められていない状況です。
以下のコードは、調べて似たような記述をまねてやってみたものです。

これでは値の取得はできなかったのですが、どこを改善していけばいいのでしょうか。

何かご教示いただけますと幸いです。
よろしくお願いいたします。

<div class="content">

                <form name="myform">
                <input name="myfile" type="file" />
                <!--  <textarea name="output" cols="100" rows="0" ></textarea>-->
                  </form>

                  <script>
                    //Form要素を取得する
                    var form = document.forms.myform;
                      //FileReaderのインスタンスを作成する
                    var reader = new FileReader();
                    var data;

                    //ファイルが読み込まれた時の処理
                    form.myfile.addEventListener('change', function(e) {

                      //ここにファイル取得処理を書く
                         var result = e.target.files[0];

                            //読み込んだファイルの中身を取得する
                            reader.readAsText( result );

                            //ファイルの中身を取得後に処理を行う
                            reader.addEventListener( 'load', function() {

                                //CSVを1行ずつ読み込む
                               console.log( reader.result.split('\n') );

                                // 2) CSVデータ変換の呼び出し
                                data = csv2Array(reader.result);
                            })

                    })

                  </script>
            </div>

                <select name="year"  id="selectbox1" class="input">
                    <option value="">選択してください</option>

                </select>
                <select name="month" id="selectbox2" class="input">
                    <option value="">選択してください</option>
                </select>
                <select name="day" id="selectbox3" class="input">
                    <option value="">選択してください</option>
                </select>

                <div class="content">

                <script type="text/javascript">

                $(function(){
                    var yearList=[],monthList=[],dayList=[];

                    for(i=13 ; i<250 ; i++){
                        if(i%8==3){
                            yearList.push(data[0][i]);
                            monthList.push(data[1][i]);
                            dayList.push(data[2][i]);
                        }
                    }

                    function(data){
                    yearList=data.yearList;
                    for(var i in yearList){
                        $("#selectbox1").append("<option value=" + yearList[i].yearNumber + ">" + yearList[i].yearName + "</option>");

                    }
                     });

                  $("#selectbox1").on('change',function(){
                    var v=$(this).val();
                    var year=yearList.filter(function(x){
                      return x.yearNumber==v;
                    });

                    $("#selectbox2 option:gt(0),#selectbox3 option:gt(0)").remove();
                    if(year.length>0){

                      monthList=area[0].monthList;

                      for(var i in monthList){
                        $("#selectbox2").append("<option value=" + monthList[i].monthNumber + ">" + monthList[i].monthName + "</option>");
                      }
                    }
                  });

                  $("#selectbox2").on('change',function(){

                    var v=$(this).val();

                    var month=monthList.filter(function(x){
                      return x.monthNumber==v;
                    });

                    $("#selectbox3 option:gt(0)").remove();

                    if(month.length>0){

                        dayList=class[0].dayList;

                         for(var i in dayList){
                        $("#selectbox3").append("<option value=" + dayList[i].name + ">" + dayList[i].name+ "</option>");
                      }
                    }
                  });
                });

                </script>
    <script type="text/javascript">

                // CSVファイルを2次元配列に変換
                function csv2Array(str) {
                  var csvData = []; //最終的な二次元配列を入れるための配列
                  var lines = str.split("\n");  //改行を区切り文字として1行ずつ読み取った配列を生成

                  //各行ごとにタグで区切った文字列を要素とした二次元配列を生成
                  for (var  i = 0; i < lines.length; ++i) {

                    var cells = lines[i].split("\t"); //タグで区切って分割する
                    csvData.push(cells);

                    //秒に変換する値を取得
                    for(var i=11;i<cells.length;i++){

                        if((i%8==3)){
                                if((cells[i] !="")){
                                    console.log(cells[i+1]); //チェック
                                    var seconds = FormatToSeconds(cells[i+1]);//実施時間
                                    console.log(seconds); //チェック
                                    cells[i+1] = seconds; //配列に戻す
                                }
                        };
                    };
                  }
                 return csvData;
                }

                //〇分〇秒⇒△秒に変換する関数(△の値のみ取得)
                function FormatToSeconds(minSec){
                        return parseInt(minSec.replace(/(\d+)分(\d+)秒/, (_, minitues, seconds) => minitues * 60 + seconds *1));
                        var seconds =  FormatToSeconds("");
                }

                //〇時間〇分〇秒⇒△秒に変換する関数(△の値のみ取得)
                function FormatToSeconds(houSec){
                  return parseInt(houSec.replace(/(\d+)時間(\d+)分(\d+)秒/, (_,hours, minitues, seconds) => hours * 3600 + minitues * 60 + seconds *1));
                    var seconds =  FormatToSeconds("");
                 }
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • kei344

    2019/03/03 17:53

    「myform」という名前の付いた要素が無いようですが、どこかにあるのでしょうか。

    キャンセル

  • ayaayape

    2019/03/03 21:47

    ご質問ありがとうございます。
    はい、contentタグのなかに、以下のように設定しています。
    <form name="myform">
    <input name="myfile" type="file" />
    </form>

    キャンセル

  • kei344

    2019/03/03 22:04

    定義されていない関数もありますし、まず最低限 動きそうなところまで質問文に追記してください。

    キャンセル

回答 2

checkベストアンサー

+1

最初プログラムの提示がなかったので丸投げかと思いました。
そういう人のためにコピペしやすいように短くして作ったのですが、
ご提示のものとは似ても似つかないようなコードになってしまいました。
せっかくなので投稿します。
短くするためにchangeイベントが1つ余計についていますが、ご愛敬。
Map の紐づけが味噌、ほんとは1行で書きたかった。 残念。

<html lang="ja">
<meta charset="utf-8">
<title></title>
<body>
<p>
<select name="y"></select>
<select name="m"></select>
<select name="d"></select>
</p>

<script>

const data = `
|2019年|1月|1日|
|2019年|1月|2日|
|2019年|1月|3日|
|2019年|1月|4日|
|2019年|1月|5日|
|2019年|1月|6日|
|2019年|1月|7日|

|2018年|2月|1日|
|2018年|2月|2日|
|2018年|2月|3日|
|2018年|2月|4日|
`,
Z = [];
for(let r,s=/(\d+年)\|(\d+月)\|(\d+日)/gm;r=s.exec(data);)Z.push(r.splice(1,3));

const
  A = (a,b,c,d,e)=>(e=b.reduce((a,b)=>a.get(b),a),e.has(c)||e.set(c,d)),
  B = (a,b)=>(a.innerText='',b.forEach(b=>a.appendChild(new Option(b,b)))),
  C = Z.map(a=>a.map(a=>''+a)).reduce((a,[b,c,d])=>(A(a,[],b,new Map),A(a,[b],c,new Map),A(a,[b,c],d,new Map),a),new Map),
  D = [...document.querySelectorAll('select')],
  E = D.reduce((a,b,c,d)=>(a.set(b,d[c+1]),a),new Map),
  F = a=>{for(let n;n=E.get(a);a=n)B(n,[...D.slice(0,D.indexOf(a)).reduce((a,b)=>a.get(b.value),C).get(a.value).keys()])};

D.forEach (a=>a.addEventListener('change',e=>F(e.target),!1)),B(D[0],[...C.keys()]),F(D[0]);

</script>

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/03/03 14:46

    ここまでくると魔法のようですね、素敵です。
    HTML部分の終了タグが</select>になっていませんので修正されてはいかがでしょう。

    キャンセル

  • 2019/03/03 14:49

    やべ!呪文唱えるので必死で・・・
    修正しました。ご指摘ありがとう。

    キャンセル

  • 2019/03/03 17:43

    回答いただきありがとうございます。
    丸投げのような質問してしまい、申し訳ありませんでした。
    こうやって設定する方法があるのですね、勉強になります。ありがとうございます
    参考にさせていただきます。

    キャンセル

0

とりあえずdata = csv2Array(reader.result);のすぐ後でdata からセレクトタグを作るコードを書く必要があります。(下記部分のコードの段階ではdataに値が入っていない可能性が高い)

                    for(i=13 ; i<250 ; i++){
                        if(i%8==3){
                            yearList.push(data[0][i]);
                            monthList.push(data[1][i]);
                            dayList.push(data[2][i]);
                        }
                    }

                    function(data){ // ここ、何故 無名関数?この書き方しても実行されないですよ。
                    yearList=data.yearList;
                    for(var i in yearList){
                        $("#selectbox1").append("<option value=" + yearList[i].yearNumber + ">" + yearList[i].yearName + "</option>");

                    }
                     }); // ここでエラーが出ない?

reader.resultを hai_haiさんの回答コードに代入すれば機能を実現することは出来ると思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/03/07 07:39

    コメント遅くなり申し訳ありません。
    ご回答ありがとうございました。
    至らない点が多くご迷惑おかけし申し訳ありませんでした。
    なんとかできそうです。本当にありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.70%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる