このサイトでは、分析、カスタマイズされたコンテンツ、および広告に Cookie を使用します。このサイトを引き続き閲覧すると、Cookie の使用に同意するものと見なされます。
Hi, Developers,
straightapps.com ロゴ
作成 November 6, 2020
トップページ > Web 開発トップ > サーバーにある CSV ファイルを読み込む
line
Web 開発
line

サーバーにある CSV ファイルを読み込んで表示します。

※ 表示が正しくないと思う場合は、JavaScript を有効にしてください。

このプログラムは、実際のサーバー環境では動作しますが、 同じ HTML ファイルや JavaScript ファイルをローカル環境、 すなわち PC のハードディスクに作成し、アクセスしても動作しません。

http://localhost/js-csvload.html のように実行する必要があり、 localhost を使うには、IIS 10 などのサーバーソフトが機能している環境が必要になります。 Win10 Pro に IIS 10 をセットアップする手順は、 「IIS 10 express をセットアップして localhost を使う」にまとめてあります。

サーバーにある csvload-attendance.csv ファイルを、下に加工して表示します。 もし「started」と表示されている場合は、JavaScript が無効か、何か問題がある状況です。



サーバーにある csv ファイル(実質テキストファイル)を JavaScript で読み込み、表示しています。 拡張子を txt に変更したもののリンクを用意しました。
csvload-attendance.txt

読み込まれる csv ファイルは、 出席番号、名前、日別の出席情報をイメージしていて、次のようになっています。

2020/10,1,ボサ,ab,ab,ok,ok,ho,ok・・・

1行目は年月の1データのみ、 2行目以降はファイルの最後まで、同じ数のデータが並んでいます。 ok は出席、ab は欠席などと決めていて、それを文字で表示しています。


現時点でのテスト済みブラウザは、

  • Windows 10 PC の Chrome
  • Android 9 スマホの FireFox
  • です。

    スマホやタブレットで開く場合は、 この QR コード ( URL の QR コード
    https://www.straightapps.com/web/js-csvload.html
    )
    が、このページの URL になっています。 QR コード読み取りアプリで読み取ると便利です。

    ▲ページ先頭へ

    ここから先は開発情報です

    投稿 November 2, 2020

    ここから先は、上記、サーバーにある csv ファイルの読み込みプログラム開発を行った際に調べたりした JavaScript コードについての情報です。

    作者背景については、「素因数分解トレーニング」のページの 「ここから先は開発情報です」をご覧ください。

    まずは、HTML 部です。

    <div id="output_data"></div>
    
    <script type="text/javascript" src="js/csvload.js"></script>
    

    div id="output_data" は、データ出力領域です。 ダウンロードした csv データを、多少は見やすい形にして、表示しています。

    JavaScript による書き換え部分はこれだけですので、 JavaScript コード csvload.js をロードしています。 スクリプトはすぐに実行され、閲覧者がボタンやリンクをクリックすることなく、 csv ファイルが 読み込まれ ( ローカルに保存されるわけではありませんので、ダウンロードしているわけではありません。 ) 、表示されています。

    以降のセクションで、それぞれ詳細を確認していきます。

    なお、ご参考までに、JavaScript ソースコードそのものを、拡張子 js を拡張子 txt に変えて、次のリンクより開けるようにしてあります。
    csvload.txt
    ※ 作成時はタブを4文字としていますので、環境によってはタブが8文字のため、 コメント等がずれて見えるかも知れません。
    ※ 念のため書き添えますが、このソースコードをこのまま転載・公開することはご遠慮ください。

    改めて書いておきますが、ローカルな環境で実行する場合、サーバーソフトが必要です。 Win10 Pro に IIS 10 をセットアップしている様子を、 「IIS 10 express をセットアップして localhost を使う」 に書いていますので、必要に応じてご参照ください。

    IIS の設定は面倒ではありますが、もちろん、いきなりサーバーでのテストは おすすめしません。 今後も JavaScript 開発を行うようでしたら、セットアップするべきだと思います。 そのほうが、開発&テストも、大幅に安全で楽になるでしょう。

    なお、IIS のセットアップのページで触れていますが、 cgi を動作させるための ActivePerl などのソフトウェアは、 csv ファイルの読み込みには必要ありません。

    ▼ セクション一覧

    ページ読み込み時の処理
    csv データを読み込む
    csv データを配列にする
    csv データを処理する

    なお、本サイトのご利用に際しては、必ずプライバシーポリシー(免責事項等)をご参照ください。

    ▲ページ先頭へ

    ページ読み込み時の処理

    投稿 November 2, 2020

    body が読み進まれていき、script の行まで到達すると、src で指定されたファイルが読み込まれます。

    <script type="text/javascript" src="js/csvload.js"></script>
    

    すべての処理は、この csvload.js にて実行されています。 一般的には </body> の直前でいいようですが、 このページでは、読みにくくならないように、 必要なすべての HTML 要素の定義が終わった直後に置いています。

    getparam.js の先頭部分は、次のような流れになっています。

    
    //----------------------------------------
    // データの出力先の用意
    
    const outputElement = document.getElementById('output_data');
    

    まずは、コードの前に、div id="output_data" を取得しています。 データ出力領域です。

    var ではなく const で outputElement を定義しているのは、 このあと outputElement の値を書き換えないためです。 var でも問題はありません。

    /*----------------------------------------
    *	CSV ファイルを読み込む関数
    *-----------------------------------------*/
    function getCsvData( dataPath )
    {
    	// 関数の中身はあとで見るので、今は省略します。
    }
    
    //----------------------------------------
    // 読み込みを実行します。
    
    outputElement.innerHTML = "started";			// 動作状況を知るため
    getCsvData( 'jsimg/csvload-attendance.csv' );		// 日本語を含む場合は Unicode 保存が必須
    

    読み込みを実行する getCsvData 関数を定義しています。 関数の中身はあとで見ますので、今は省略します。

    実行の状況を掴むため、output_data 領域に started と表示します。 サーバーではないローカルな環境で実行した場合、 getCsvData 関数が動作しませんので、started が表示されたままになります。 なお、innerHTML によるテキストの書き換えについては、 「【基礎】HTML 要素のテキストの書き換え」に書いています。

    最後に getCsvData 関数に、引数として読み込みたい csv ファイル名を渡して、処理してもらいます。

    関数の定義になっていない、 つまり読み込み時に実行されるのはこの部分だけです。 これよりあとの関数定義は、getCsvData 関数から呼び出されるものとなっています。

    ▲ページ先頭へ

    csv データを読み込む

    投稿 November 4, 2020

    csvload.js が読み込まれると、
    getCsvData( 'jsimg/csvload-attendance.csv' )
    のように、この関数 getCsvData が呼び出されます。 引数は、読み込みたいファイル名になっています。

    このリンクから、拡張子を txt に変更したものを参照できるようにしてあります。
    csvload-attendance.txt

    関数の内容を、順にみていきます。

    function getCsvData( dataPath )
    {
    
    	// HTTP でファイルを読み込むための XMLHttpRequest オブジェクトを生成します。
    	var req = new XMLHttpRequest();
    

    変数 req に、XMLHttpRequest オブジェクトを作成し、設定します。

    XMLHttpRequest オブジェクト ( XHR オブジェクトと呼ぶようです。 ) は、サーバーと対話するために使用され、ページ全体を更新しなくてもデータを受け取ることができ、 ウェブページの一部を更新できるようにするための仕組みだそうです。 詳しくは、「XMLHttpRequest」に書かれています。

    これがないとファイルにアクセスできないようです。以下で使用します。

    XMLHttpRequest オブジェクトは、実際のサーバー環境では動作しますが、 ローカルな環境で実行したい場合は、サーバーソフトがセットアップされている必要があります。 この関数を PC のハードディスクに作成し、アクセスしても動作しません。

    ローカルな環境で実行するには、
    http://localhost/js-csvload.html
    のようにアクセスして実行する必要があります。 これは、ローカルな環境でサーバーの代わりをするソフトが入っている場合のアクセス方法です。 サーバーソフトがセットアップされていても、この形でアクセスしなければ、成功しません。
    C:\inetpub\wwwroot\js-csvload.html
    では、希望の動作にはなりません。

    localhost を使うには、 Windows の場合、 IIS ( Internet Information Services ) 10 などのサーバーソフトを実行している環境が必要になります。 Win10 Pro に IIS 10 をセットアップする手順は、 「IIS 10 express をセットアップして localhost を使う」にまとめてあります。

    	// ファイルを読み込みます。
    	req.open("get", dataPath, true);	// アクセスするファイルを指定
    	req.send(null);			// HTTP リクエストの発行(引数は省略できる模様)
    

    XHR オブジェクト ( XMLHttpRequest オブジェクトの変数 req ) open 関数に、 文字列 "get"、読み込みたいファイル名、そして true を渡して、読み込みたいファイルを設定します。

    最初の文字列 get は、HTTP リクエストメソッドであるとされています。 get のほか、post、put、delete が利用できるようです。

    第2引数はファイル指定で、DOMString であるということですが、 特に文字種変換などなしに成功しているので、気にしなくていいのかも知れませんし、 環境により失敗するのかも知れません。

    最後の true はオプションで既定値が true とされていますので、記述する必要はなさそうです。 非同期で読み込む、という指定になります。 つまり、読み込み完了まで処理を進めるのを待つことがありませんので、 ページ表示のレスポンスが良くなると考えられます。 読み込むファイルが大きくなると、または処理時間が長くなると、 いったんデータ表示なしで表示され、そのあと書き換えられる、 という動作になると思われます。

    このあと、ユーザー名とパスワードも指定できますので、 プロテクトされた領域にあるファイルにもアクセスできそうです。 ですが、JavaScript 内にユーザー名とパスワードを書き込むと、 誰でも見ることができてしまうため、危険です。

    この open 関数呼び出しは設定を行うのみですので、 実行するには send 関数を呼び出さなくてはいけません。 send 関数を呼び出すと、リクエストがサーバーに送信されます。

    	// レスポンスが返ってきたら、データを処理します。
    	//    無名関数を使わない場合 req.addEventListerner("load", onLoad);
    	req.onload = function(){
    
    		// 読み込んだ CSV データをそのまま見たい場合
    		//outputElement.innerHTML = req.responseText;
    
    		// 読み込んだ CSV データを2次元配列に変換します。
    		let dat = convertCSVtoArray( req.responseText );
    
    		// 好きなように処理します。
    		procData(dat);
    	}
    }
    

    onload イベントは、読み込みが完了したときに発生します。 読み込みが完了したら、ここに定義されている、引数なしの無名関数が実行されることになります。 わかりやすいように function と書いていますが、なくてもいいはずです。

    読み込んだデータは req.responseText に格納されますので、 そのまま様子を見たい場合は、上記ではコメントになっていますが、 出力領域 div id="output_data" を指す outputElement の innerHTML に、そのまま設定すれば確認できます。

    今は、csv データを参照したり、加工して表示したいので、 下記の convertCSVtoArray 関数にデータ文字列を渡して、 2次元の配列に分解しています。

    最後に procData 関数で、好きなように加工して画面に表示しています。

    もちろんそのまま表示する必要はありませんから、ゲームデータを読み込んで反映させたり、 という使い方ができると思います。

    なお、csv データは Windows 標準のメモ帳でも作成できますが、 日本語を使う場合、「名前を付けて保存」で文字コードを UTF-8 指定をしないと、 正しく表示されない可能性があります。

    メモ帳の名前を付けて保存

    「文字コード」を ANSI から UTF-8 に変更して保存します。

    文字コード欄を UTF-8 に変更

    メモ帳は、このあと設定を記憶していて、新しくファイルを作成すると UTF-8 で保存しようとするようですので、 ANSI で保存したい場合には気にしておく必要があります。 ANSI のファイルを開いた場合はそのままとなり、UTF-8 で上書きすることはなさそうです。

    ANSI で保存すると、次のように文字化けします。

    文字コードが違うので文字化け

    ▲ページ先頭へ

    csv データを配列にする

    投稿 November 5, 2020

    読み込まれる csv ファイルは、次のようになっています。

    2020/10
    1,ボサ,ab,ab,ok,ok,ho,ok
    2,コンウェイ,ok,ok,ab,ok,ho,ok
    3,ドワイト,ok,ea,ok,ea,ho,ea
    

    1行目は1データのみ、 2行目以降はファイルの最後まで、同じ数のデータが並んでいます。

    これを2次元配列に格納できれば、アクセスしやすくなります。

    /*----------------------------------------
    * 引数の CSV データを行単位の配列に変換
    *-----------------------------------------*/
    function convertCSVtoArray(csv)
    {
    	var result = [];				// 最終的な二次元配列を入れるための配列
    	var tmp = csv.split("\r\n");			// 改行を区切り文字として行を要素とした配列を生成(Winの場合は\r必要)
    
    

    変数 result は、最終的に2次元配列となる予定です。 ここでは、要素数不明の1次元配列として定義しています。 要素数不明の1次元配列の取り扱いについては、 「【基礎】可変サイズの配列と操作」に書いています。

    変数 tmp には、引数として受け取った csv データ csv に対して、 split 関数\r\n を渡して、 改行コードごとに分割された、1次元配列が設定されます。 tmp 配列のそれぞれの要素には、1行のデータが設定されます。

    なお、改行コードを \r\n としていますが、 ネット上では \n だけで判断しているものがあります。 csv ファイルの作成環境によるのかも知れませんが、 Windows(のメモ帳)で作成する限りでは \r\n になりましたので、 こうしています。 環境によっては正しく判定されない可能性もありますが、 例えそうであっても、csv ファイルを作成する側の問題ですから、 これでいいと思います。

    もし改行コードが \r\n で作成されたファイルを \n で split すると、 文字列のあとに \r が残って、正しく比較できなくなる場合があるようでした。

    	// 行ごとにカンマで区切った文字列を要素とした二次元配列を生成
    	for (let i = 0; i < tmp.length; i++){
    		if (tmp[i] != ""){			// 空行を除外(特にファイル末尾)
    			result[i] = tmp[i].split(',');
    		}
    	}
    
    	return result;
    }
    

    1要素1行となった配列 tmp の要素数だけ、ループして処理します。 1次元配列の要素数は、length プロパティに入っています。

    念のため空行を除外して、 1次元配列 result の各要素に、カンマで区切られた文字列を分解して、 1次元配列として格納します。 1次元配列の各要素が1次元配列となりますので、結果として2次元配列として扱えるようになります。

    ▲ページ先頭へ

    csv データを処理する

    投稿 November 6, 2020

    2次元配列になった csv データを、引数 dat で受領して、 わかりやすいように加工して表示するための関数です。

    function procData(dat)
    {
    	// CSV 1行目は年月情報
    	let str = dat[0][0] + " の出欠情報<br/>";
    

    1行目は年月情報だけが入っているとしています。 dat[ 0 ] に1行目の情報が、1次元配列の形で入っていますから、 その最初の要素へのアクセスは、dat[ 0 ][ 0 ] となります。

    変数 str には、最終的に出力したい HTML テキストを入れますので、 改行が必要な部分では <br/> などを書き込めます。

    	// CSV 2行目以降は 番号,名前,1日からの出欠情報・・・
    	for (let row = 1; row < dat.length; row++){
    
    		// 1カラム目は出席番号
    		str += ("No." + dat[row][0] + " : ");
    
    		// 2カラム目は名前
    		str += (dat[row][1] + "<br/>   ");
    

    2行目のデータは dat[ 1 ] に、3行目のデータは dat[ 2 ] に・・・と格納されていて、 最後の行まで出欠データであるとしていますので、最後の行データまでをループ処理します。 1次元配列としての dat の要素数は、dat.length でわかります。

    1行の行データは、次のようになっています。

    1,ボサ,ab,ab,ok,ok,ho,ok
    

    行データ内のデータは、dat[ row ] に、 1次元配列として格納されていますので、 dat[ row ][ 0 ] には出席番号が、 dat[ row ][ 1 ] には名前が、 そしてそれ以降には日別の出席情報が記録されていることとなっています。

    上の部分では、str に出席番号と、名前を追記しています。 += で文字列の追記ですので、 念のため、右辺をカッコでくくって先に連結されるように指定しています。 こう書かなくても問題ないようです。

    		// 3カラム目以降は出欠状況
    		//    "ok"  出席
    		//    "ab"  欠席
    		//    "lt"  遅刻
    		//    "ea"  早退
    		//    "le"  遅刻&早退
    		//    "ho"  休日
    		for (let col = 2; col < dat[row].length; col++){
    

    3カラム目以降は日別の出欠情報で、日ごとに追加されると想定すれば可変個数となりますから、 dat[ row ] の要素数の最後、dat[ row ].length までループさせています。

    			switch (dat[row][col])
    			{
    				case 'ok':
    					str += '<span class="mkPink">出席</span>';
    					break;
    
    				case 'ab':
    					str += '<span class="red strong">欠席</span>';
    					break;
    
    				case 'lt':
    					str += '<span class="blue">遅刻</span>';
    					break;
    
    				case 'ea':
    					str += '<span class="blue">早退</span>';
    					break;
    
    				case 'le':
    					str += '<span class="blue">遅刻&早退</span>';
    					break;
    
    				case 'ho':
    					str += '<span class="red sz80p">休日</span>';
    					break;
    
    				default:
    					str += ('<span class="mkB">' + dat[row][col] + '</span>');
    					break;
    			}
    

    1つの出欠データは、dat[ row ][ col ] でアクセスできますので、 ケース別に、出力する文字を日本語にして HTML に追加しています。 ok なら「出席」、 ab なら「欠席」のようにしています。

    なお、グレーにしている class の部分は、css で定義した装飾です。 mkPink はピンクのマーカー、red は赤文字、strong は太文字などです。 なので、動作としては何も影響はありません。

    念のため、想定外の値を default で拾い、 そのまま出力するようにしています。

    			if (col < dat[row].length - 1){		// 最終項目でなければ
    				str += ", ";
    			}
    		}
    		str += "<br/>";
    	}
    	outputElement.innerHTML = str;
    }
    

    最後の項目を出力したのでなければ、カンマで区切るようにしています。

    最後の項目まで出力したら、改行し、ループを続けます。

    出力したい HTML 文字列が str に入ったら、outputElement に入っている div id="output_data" に出力します。

    ▲ページ先頭へ
    line
    関連トピックス
    line


    その他のおすすめ

    ウェブ開発に関するトピックは、「ウェブ開発トップ」にまとめられています。



    © 2017-2020 StraightApps.com 無断転載を禁じます。No reproduction without permission.