2019年2月11日月曜日

とりあえず、node.jsでサーバーサイド処理を作り、SQL-Serverデータをブラウザ表示する

今回の記事では、今までコンソール動作ばかりさせてみたnode.jsですが、個人的に三連休の間にやりたいリストに入れていた事をギリギリで達成してみたいと思います。

それは、node.jsでサーバーサイド処理を作り、SQL-Serverから取得したデータをブラウザに表示するまでとりあえずでもいいからやってみる、という事です。

あまり動きをよく掴めていないので、試行錯誤しながらでしたが何とか出来ました。


■仕様

  • パラメータや入力は無し。表示だけ。
  • 表示データはSQL-Serverから取得します。
  • コンソールではなく、ブラウザに描画します。
  • 画面とコードは別ファイルに分けます。
■実行してみる

↑実行はコンソールからです。

実行に成功すると、メッセージをコンソールに表示するようにしてあり、あとはずっとlocalhost:1234でWebサーバーとしてクライアントからのアクセスを待ち受けするようになっています。


↑localhost:1234にアクセスすると、今回の処理が走ります。

SQL-Server経由で、Excel 2019に自分で勉強した時に作り続けているナレッジベースに接続し、その内容を取得。

コンソール画面ではなく、HTMLを使ってブラウザに表示します。


↑単に表示するだけですが、見たい列だけを取捨選択出来るようにだけはしてあります。

ただ、画面を動的に作るのってどうするのか?? フレームワークを使わない生のnode.jsはなかなか難しい感じで、くるくると私の悪い頭を振り絞って自己流で原始的な方法でやってみました。


■プログラムコード(TEST2.js)



/**
 * @fileoverview ナレッジベースをとりあえずブラウザ表示するテスト
 */

/**
 * 確認用変数
 */
let aSqlData = new Array();
let sHTML = "";

/**
 * 接続オブジェクト定義
 */
let SqlConObject = require('tedious').Connection;
let config = {
    server  :'E203MA',
    authentication:{
        type     : 'default',
        options  : {
            userName : 'ログインID',
            password : 'パスワード'
        }
    },
    options :{
        instanceName:'EXPRESS2017',
        encrypt :false,
        database:'MAINDB'
    } 
};
let SqlCon = new SqlConObject(config);
let i = 0;
let j = 0;
let SqlReqObject = require('tedious').Request;

/**
 * Event
 * サーバー接続
 */
SqlCon.on('connect', function(err) {
    if ( err ) {
        console.log('接続エラー(' + err + ')');
        process.exit();//終了
    }
    procSqlExecute();
});

/**
 * Function
 * サーバー接続時処理
 */
function procSqlExecute() {
    let SqlStr = "SELECT T.* ";
        SqlStr+= "FROM OPENROWSET(";
        SqlStr+= "    'Microsoft.ACE.OLEDB.16.0'";
        SqlStr+= "   ,'Excel 12.0;DataBase=D:¥¥OneDrive¥¥HOME¥¥MAIN_DATA¥¥知識¥¥ナレッジベース.xlsx'";
        SqlStr+= "   ,'SELECT TOP 5 * FROM [学習$]') AS T ";
        SqlStr+= "WHERE [ジャンル] IS NOT NULL "
        
    let SqlReq = new SqlReqObject(SqlStr, function(err, rows) {
        if ( err ) {
            console.log('リクエストエラー(' + err + '');
            process.exit();
        }
        SqlCon.close();
    });

    /**
     * Event
     * クエリーリクエスト時
     */
    SqlReq.on('row', function(SqlRows) {
        aSqlData[i] = new Array();
        j=0;
        //@@@@@@@@@@[LOOP-START]@@@@@@@@@@
        SqlRows.forEach(function(SqlColumn){
            aSqlData[i][j]=SqlColumn.value;
            j++;
        })
        //@@@@@@@@@@[LOOP-START]@@@@@@@@@@
        i++;
    });

    /**
     * Event
     * クエリーリクエスト終了処理
     */
    SqlReq.on('requestCompleted',function(){
        //console.log(aSqlData);
        //console.log("( " + i + " )件ありました!");
        sHTML = CreateHTML(aSqlData);
        BeginServerConsole();
    });
    /**
     * クエリーの実行
     */
    SqlCon.execSql(SqlReq);
}

/**
 * Webサーバー処理部分
 */
/**
 * Webサーバー処理
 */
function BeginServerConsole() {
    let http = require("http");
    let server = http.createServer();
    server.on('request', serverProc);

    let fs   = require("fs");
    
    /**
     * Function
     * サーバー処理関数
     * @param {object} req 
     * @param {object} res 
     */
    function serverProc(req, res) {
        fs.readFile(__dirname + '¥¥TEST2.html','utf-8'
            ,function(err, data) {
                res.writeHead(200,{'Content-Type':'text/html;charset=utf-8'});
                data = data.replace(/¥{0¥}/,sHTML);
                res.write(data);
                res.write(aSqlData[0][0] + "<br/>");
                res.end();
            }
        );
    }
    
    /**
     * Event
     * サーバー待ち受け
     */
    server.listen(1234,'127.0.0.1'
        ,function() {
            console.log('物理パスは' + __dirname + 'です...');
            console.log('Webサーバー開始しました...');
        }
    );

}

/**
 * Function
 * HTMLエスケープ処理
 * @param  {string} value
 */
function EscapeHTML(value) {
    //↓ここの&は半角にしてね!ブログに載せる都合で全角にしてます
    return new String(value).replace(/</g,"&lt;")
                            .replace(/>/g,"&gt;")
                            .replace(/&/g,"&amp;")
                            .replace(/"/g,"&quot;")
                            .replace(/`/g,"&#x60;")
                            .replace(/'/g,"&#x27;");
}
/**
 * FUNCTION
 * SQL-Serverのデータを画面描画用に作成
 * @param  {object} aSqlData
 * @param  {object} res
 */
function CreateHTML(aSqlData) {
    let i = 0;
    let j = 0;
    let sRes = "";

    if(aSqlData.length > 0) {
        /**
         * ヘッダの描画
         */
        sRes +="<thead>";
        //@@@@@@@@@@[LOOP-START]@@@@@@@@@@
        for(i=0;i<aSqlData[0].length;i++){
            sRes+="<th class='ui-width-25p' data-priority='" + (i+1) + "'>";
            sRes+="ヘッダ" + (i+1);
            sRes+="</th>";
        }
        //@@@@@@@@@@[LOOP-END  ]@@@@@@@@@@
        sRes+="</thead>";
        /**
         * 明細の描画
         */
        sRes+="<tbody>";
        //@@@@@@@@@@[LOOP-START]@@@@@@@@@@
        for(i=0;i<aSqlData.length;i++){
            sRes+="<tr>";
            //@@@@@@@@@@[LOOP-START]@@@@@@@@@@
            for(j=0;j<aSqlData[i].length;j++){
                sRes+="<td>";
                sRes+=EscapeHTML(aSqlData[i][j]);
                sRes+="</td>";
            }
            //@@@@@@@@@@[LOOP-END  ]@@@@@@@@@@
            sRes+="</tr>";
        }
        //@@@@@@@@@@[LOOP-END  ]@@@@@@@@@@
        sRes+="</tbody>";
    }
    return sRes;
}



■画面(TEST2.html)


<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="utf-8">
        <title>ハローワールドASUS E203MA</title>
        <style>
            tr {
                border-bottom:1px solid Silver;
            }
            tr:nth-child(even) {
                background-color:silver;
            }
            th {
                background-color:gray;
            }
            .ui-width-25p {
                width:25%;
            }
        </style>
        <link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.0/jquery.mobile-1.4.0.min.css" />
        <script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
        <script src="http://code.jquery.com/mobile/1.4.0/jquery.mobile-1.4.0.min.js"></script>
    </head>
    <body>
        <div data-role="page" id="page1">
            <div data-role="header">
                <h1>ASUS E203MA</h1>
            </div>
            <div data-role="content" class="ui-content" style="text-align:center;">
                <table data-role="table" 
                       data-mode="columntoggle" 
                       class="ui-responsive ui-shadow" 
                       data-column-btn-text="列選択"
                       id="myTable" >
                    <!--↓サーバーサイドコードブロック-->
                    {0}
                    <!--↑サーバーサイドコードブロック-->
                </table>

            </div>
            <div data-role="footer">
                <h3>Node.jsで表示したよ!</h3>
            </div>
        </div>

    </body>
</html>


↑動的に画面を書き換えると言っても、本当に原始的で単純なやり方です。

HTML側に、書き換えたいコードブロック部分をマーカーとして設けておいて、そこをリプレースしてブラウザにぶっこむだけ。

ただ、自分なりに、だんだんとnode.jsのサーバーサイド処理の仕組みが実感出来るようになって来ました。

なかなか、他にも勉強したい事がたくさんありすぎて、node.jsだけやれないのですが、これ本当に楽しいですね。

まったりとPCをいじるのは小さな幸せーです。