JavaScript
intra-mart
SheetJS
データベース更新

SheetJSを使って、データベースの登録にトライ

概要

「tabulatorを使って、データベースを更新」)に続いて、sheetjsを使ってExcelをドラッグ&ドロップするとデータベースを登録するサンプルを作成してみました。サーバ側は「Open intra-mart」です。

従来は、Apache POIをサーバ側にインストールして、サーバにExcelを投げてからサーバサイドで処理をしてExcelの内容をデータベースに登録していましたが、sheetjsを利用する事で、簡単にExcelの内容を登録する事ができました。

参考サイト

※Open intra-mart(再掲)
※sheetjs
※DBアクセスについてはこちらのDatabaseManagerを利用しています(再掲)。

画面キャプチャー

sheetjs_sample.jpg

DEMO(Azureが無償モードでアクセスの都度に立ち上がるので起動に時間がかかります。)左に添付しているExcelをダウンロードして、編集してページにドラッグするとその内容がテーブルに登録されます。

ソースはこちら

sheetjsのjs-xlsx-master.htmlというサンプルをシンプルに削って、シートのデータを取り出すところを追加しただけです。(勉強用のコメントが残していますが。」)
ポイントは「ここで読み込んだワークシートが扱える」のところです。

  var sheet_name = "Sheet1";            // ・・・シート名を指定して
  var worksheet = workbook.Sheets[sheet_name];  // ・・・ワークブックからシートを取り出して
  name        = worksheet["A" + String(i)].v;   // ・・・セル名称を与えて.Vで値がとりだせます
SheetJS_demo.html
<!DOCTYPE html>
<html>
<head>
    <title>SheetJS Live Grid Demo</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <link rel="stylesheet" href="/im-jssp-sample/SheetJS/assets/css/sheetjs.css">
</head>

<!--****************************************
* BODY
*****************************************-->
<body>
    <script src="/im-jssp-sample/SheetJS/assets/vendor/alertify.js"></script>
    <script src="/im-jssp-sample/SheetJS/assets/js/canvas-datagrid.js"></script>

    <link rel="stylesheet" media="screen" href="/im-jssp-sample/SheetJS/assets/vendor/samples.css">
    <link rel="stylesheet" media="screen" href="/im-jssp-sample/SheetJS/assets/vendor/alertify.css">

    <div id="logo"><img src="/im-jssp-sample/SheetJS/assets/img/logo.png" class="logo" alt="SheetJS Logo"  width=128px height=128px/></div>

    <div id="body">
        <div id="left">
            <div id="drop">Drop a file here</div>

            <!--ファイル読込しなくてもxlfとbuttonは必要 input type="file" name="xlfile" id="xlf" value=""><div id="buttons"></div-->           
            <div id="xlf"></div><div id="buttons"></div>

            <b>Advanced Demo Options:</b>
            Use Web Workers: (when available) <input type="checkbox" name="useworker" checked>
            Use readAsBinaryString: (when available) <input type="checkbox" name="userabs" checked>

            <p><b><a href="im-jssp-sample/images/首相一覧.xlsx">sample:首相一覧.xlsx</a></b></p>

        </div>


        <div id="right">
            <div id="grid"></div>
            <div id="footnote"></div>
            <div id="htmlout"></div><br>
        </div>


    </div>

    <IMART type = "jsspRpc" 
        name = "SheetJS" 
        page = "SheetJS/SheetJS" >
    </IMART>

<!--****************************************
* スクリプト:ヘダーだと動かない
*****************************************-->

<script src="/im-jssp-sample/SheetJS/assets/js/shim.js"></script>
<script src="/im-jssp-sample/SheetJS/assets/js/xlsx.full.min.js"></script>
<script src="/im-jssp-sample/SheetJS/assets/js/dropsheet.js"></script>
<script src="/im-jssp-sample/SheetJS/assets/js/main.js"></script>
<script src="/im-jssp-sample/SheetJS/assets/vendor/spin.js"></script>

<!--****************************************
* ここからjs-xlsx-masterのスクリプト
*
* 本当はExcel読込後に修正したのでデータ登録したかったが無理だった
*
*****************************************-->
<script>

var X = XLSX;
var XW = {
    /* worker message */
    msg: 'xlsx',
    /* worker scripts */
    worker: '/im-jssp-sample/SheetJS/assets/js/xlsxworker.js'
};

var global_wb;

/**********************************************************************
* do_file:起動時2
**********************************************************************/
//*process_wb(wb)Excelドロップ5
var process_wb = (function() {

    var HTMLOUT = document.getElementById('htmlout');

//* HTML Excelドロップ6
    var to_html = function (workbook) {

        //シートデータを画面へ表示
        HTMLOUT.innerHTML = "";
        workbook.SheetNames.forEach(function(sheetName) {
            var htmlstr = X.write(workbook, {sheet:sheetName, type:'binary', bookType:'html'});
            HTMLOUT.innerHTML += htmlstr;
        });

//ここで読み込んだワークシートが扱える
//      var base_column = 'A';
        var start_row = 2;
        var sheet_name = "Sheet1";
        var worksheet = workbook.Sheets[sheet_name];
        for(var i = start_row; worksheet["A" + String(i)].v !== undefined; i++) {
            name        = worksheet["A" + String(i)].v;
            age         = worksheet["B" + String(i)].v;
            adress      = worksheet["C" + String(i)].v;
            code        = worksheet["D" + String(i)].v;
            dateofbirth = worksheet["E" + String(i)].v;

            add_sec(name,age,adress,code,dateofbirth);
        }
        return "";
    }

    return function (wb) {
        global_wb = wb;
        var output = "";
        output = to_html(wb)
    };
})(); //process_wb

/**********************************************************************
* do_file:起動時2
**********************************************************************/
var do_file = (function() {

    //FileAPIのreadAsBinaryString(オワコンになってreadAsArrayBuffer変更されるらしい)
    var rABS = typeof FileReader !== "undefined" && (FileReader.prototype||{}).readAsBinaryString;
    var domrabs = document.getElementsByName("userabs")[0];
    if(!rABS) domrabs.disabled = !(domrabs.checked = false);

    //ウェブ ワーカーは、ウェブ アプリケーションでバックグラウンドスクリプトを生成するための API 
    var use_worker = typeof Worker !== 'undefined';
    var domwork = document.getElementsByName("useworker")[0];
    if(!use_worker) domwork.disabled = !(domwork.checked = false);

//Excelドロップ4
    var xw = function (data, cb) {
        var worker = new Worker(XW.worker);
        worker.onmessage = function(e) {
            switch(e.data.t) {
                case 'ready': break;
                case 'e': console.error(e.data.d); break;
                case XW.msg: cb(JSON.parse(e.data.d)); break;
            }
        };
        worker.postMessage({d:data,b:rABS?'binary':'array'});
    };

//Excelドロップ3
    return function (files) {
        rABS = domrabs.checked;
        use_worker = domwork.checked;
        var f = files[0];
        var reader = new FileReader();
        reader.onload = function(e) {
            if(typeof console !== 'undefined') console.log("onload", new Date(), rABS, use_worker);
            var data = e.target.result;
            if(!rABS) data = new Uint8Array(data);
            if(use_worker) xw(data, process_wb);
            else process_wb(X.read(data, {type: rABS ? 'binary' : 'array'}));
        };
        if(rABS) reader.readAsBinaryString(f);
        else reader.readAsArrayBuffer(f);
    };
})();  //do_file


/**********************************************************************
* drop  ドロップで読込:起動時3
**********************************************************************/
(function() {
    var drop = document.getElementById('drop');
    if(!drop.addEventListener) return;

    //ファイルドラッグの次にここが反応する。Excelドロップ2
    function handleDrop(e) {
        e.stopPropagation();
        e.preventDefault();
        do_file(e.dataTransfer.files);
    }

    //ファイルをドラッグするとここが反応する。Excelドロップ1
    function handleDragover(e) {
        e.stopPropagation();
        e.preventDefault();
        e.dataTransfer.dropEffect = 'copy';
    }

    drop.addEventListener('dragenter', handleDragover, false);
    drop.addEventListener('dragover', handleDragover, false);
    drop.addEventListener('drop', handleDrop, false);
})();

/**********************************************************************
* xlf  ファイルを指定して読込:起動時4  ドラッグ&ドロップの時もこのfunction必要
***********************************************************************/

(function() {
    var xlf = document.getElementById('xlf');
    if(!xlf.addEventListener) return;
    function handleFile(e) { do_file(e.target.files); }
    xlf.addEventListener('change', handleFile, false);
})();

/********************************
* add
********************************/
function add_sec(name,age,adress,code,dateofbirth){
    var result = SheetJS.addData(
        name,
        age,
        adress,
        code,
        dateofbirth
    )
    alert("★to_htmlで登録name=" + name + " age=" + age + " adress=" + adress + " code=" + code + " dateofbirth=" + dateofbirth + " 登録結果t=" + result);

}
</script>

</body>
</html>

SheetJS.js
/**
 * SheetJS  DB登録用
 */
load("lib/DatabaseManager");
/*****************************
 * テーブルインサート
 *****************************/
function addData(name,age,adress,code,dateofbirth) {

    Debug.print("addDataロジックです:" + nowtime());
    Debug.print( "name = " + name + " [" + typeof name + "]");
    Debug.print( "age = " + age + " [" + typeof age + "]");
    Debug.print( "adress = " + adress + " [" + typeof adress + "]");
    Debug.print( "code = " + code + " [" + typeof code + "]");
    Debug.print( "dateofbirth = " + dateofbirth + " [" + typeof dateofbirth + "]");

    var databaseManager = new DatabaseManager(true);
    var rows;
    var params = [];

    /**
     *
     * @param {IfRubbishDatabase}   dbh
     */

    params[0] = dateofbirth;
    params = DatabaseManager.changeParams( params ); 
    function handler(dbh)
    {

        dbh.insertBy("test", function(row) {
            row.name = name;
            row.age = age;
            row.adress = adress;
            row.code = code;
//          row.dateofbirth =  dateofbirth;
            row.dateofbirth =  params[0]; 
            });
    }
    var result = databaseManager.connect(handler);
    if ( result.getError() )
    {
        throw new Error( result.getErrorMessage() );
    }

    return "ok";
}

おわりに

メンバーへのスキトラも兼ねて、書いていますが、普段こういった投稿をしていないもので、なかなか大変ですね。いろいろ参考になる記事を投稿している皆さんには頭が下がります。また何かネタができましたら投稿したいと思います。