Gridで合計行を表示

参考
こちらのサイトの記事を参考にさせてもらいました。
Gridでデータを入力できるようにしていたら,「合計を表示できないか」といわれまして,なんとかそれを実現すべく考えました。対象はExt3です。

合計行を表示するには,グリッドに合計行を加えるか,合計用のグリッドを用意するかですが,縦スクロールしても合計行が画面からはみ出ないようにしたいので,合計用のグリッドを用意することにしました。合計行を表示させるためにやらなければならないことは次のとおりです。

  1. 明細グリッドと合計グリッドの横スクロールを同期させる。
  2. 明細グリッドの横スクロールバーはいらないので表示させない。
  3. 明細グリッドで列幅を変更したら合計グリッドの列幅も変更する。
  4. 明細グリッドで列を移動したら合計グリッドの列も移動する。
  5. 合計の計算をする。

順番に解決していきましょう。とその前に,完成時のスクリーンショットを載せておきます。

と,こんな感じになります。数値列はちゃんと右寄せしろよ!って感じですが。

横スクロールを同期させる

横スクロールバーは合計グリッドにのみ存在しますので,合計グリッドのスクロールが発生したら,明細グリッドをスクロールさせるだけでいいような感じがしますが,明細グリッドの入力時にキー入力によって明細グリッドにスクロールが起こることがあるので,双方のグリッドのスクロールイベントをリッスンして同期を取る必要があります

    onSumScroll: function( left, top ){

        var me = this;

        me.syncScroll( me.grdData, left, top );
    },

    onDataScroll: function( left, top ){

        var me = this;

        me.syncScroll( me.grdSum, left, top );
    },

    syncScroll: function( tgt, left, top ){
        var me = this;
        var con = tgt.getEl().child('*[class*=x-grid3-scroller]');

        con.scrollTo( "top", top, false );
        con.scrollTo( "left", left, false );

    },

参考サイトでは,ExtJS2なのでscrollToの引数が違っています。こちらはExt3のコードです。onSumScroll を 合計グリッドの bodyscroll イベントにセットし,onDataScroll を 明細グリッドの bodyscroll イベントにセットします。

明細グリッドの横スクロールバーを消す

スクリーンショットのように明細グリッドと合計グリッドは上下に並べて表示させます。二つのグリッドは同期してスクロールされるので,明細グリッドには横スクロールバーは不要です。それを表示させないようにします。

    onAfterRender: function() {

        var me = this;
        var el = me.grdData.getEl().child('*[class*=x-grid3-scroller]');

        el.setStyle('overflow-x', 'hidden');
    },

これはフォームのafterrenderイベントのコードです。ここで明細グリッドの横スクロールバーを表示させないように,エレメントのoverflow-xをfalseに変更しています。

列幅の変更も同期

列幅が変更されたときに,合計グリッドの列幅も変更します。

    syncColumnResize: function( columnIndex, newSize) {
        var me = this;

        me.grdSum.colModel.setColumnWidth(columnIndex, newSize);

    },

明細グリッドの columnresize イベントで上記のメソッドがコールされるようにします。単にそのまま setColumnWidth メソッドをコールしているだけです。

列の移動も同期

同様に列の移動を同期しようと,

    syncColumnMove: function( columnIndex, newIndex ){
        var me = this;

        me.grdSum.colModel.moveColumn(columnIndex, newIndex);

    },

と書いてみましたが,なぜか動きません。そしてこのメソッドが動いた後,なんだか動きが編になります。(´・ω・`) 現在調査中。

うまく動作しない理由がわかりました。明細・合計それぞれのcolModelをnewするときにコンフィグを指定しますが,両方とも同じ構造ですから,一つの配列を渡していました。それでおかしくなっちゃっていたのです。コンフィグの配列を別のものにするとちゃんと動きました。別な勉強をしました。

合計の計算をする

合計行ということですからデータから合計を計算しなければ行けません。1つの列の合計をとるメソッドを用意。

    calcSum: function(colName){

        var me = this;
        var dataStore = me.grdData.getStore(),
            sumStore = me.grdSum.getStore();
        var dataRec,
            sumRec = sumStore.getAt(0),
            row, val=0;

        for( row = 0; row < dataStore.getCount(); row++ ){
            dataRec = dataStore.getAt( row );
            val += dataRec.get(colName);
        }
        sumRec.set(colName, val);
        sumStore.commitChanges();
    },

まず,明細ストアのデータがロードされたときに全コラムを計算します。

        me.store.load({
            callback: function () {

                me.calcSum('money1');
                me.calcSum('money2');
                me.calcSum('money3');
                me.calcSum('money4');
                me.calcSum('money5');

            }
        });

コラムが多い場合はもっとスマートな書き方を考えましょうね。あとは明細グリッドが変更されたときに対象となるコラムだけを再計算させます。

    onAfterEdit: function(e){

        var me =this,
            fld = e.field;

        me.calcSum(fld);
    },

この場合は,EditorGridPanel のafteredit イベントにセットしています。

Gridで合計行を表示」への1件のフィードバック

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です