Curl Global Community
合計行の表示 - Printable Version

+- Curl Global Community (https://communities.curl.com)
+-- Forum: Discussions (https://communities.curl.com/forumdisplay.php?fid=1)
+--- Forum: General Curl questions (https://communities.curl.com/forumdisplay.php?fid=2)
+--- Thread: 合計行の表示 (/showthread.php?tid=896)



合計行の表示 - umemura - 05-15-2013

グリッドに合計行を表示と思ったら、どんな方法がありますか?
合計行用のレコードを追加して、レコード変更イベントで合計計算をする、というのはわかりそうなのですが、
行位置を固定したいのでソートされた場合のハンドリングや、
そのレコードのみ入力不可にするためのカスタムセルの実装など、
いろいろ意識するポイントがあるかと思います。

実装上のテクニックなどあれば教えてください。




RE: 合計行の表示 - umemura - 05-15-2013

最上行に表示するのであれば、ソートや行列の固定を利用(オーバーライドも必要?)すれば、何とか実装できそうな気がしていますが、
最下行として表示する方法についてはうまく思いつきません。
(最下行のレコードを対象に行列の固定をすると、スクロールできなくなってしまうため)


エクセルなどでも、合計行は、通常、下の方に表示することが多いと思いますが
Curl を利用した業務画面では、どのようなレイアウト実装をすることが多いのでしょうか。


Code:
{value
    def rfs =
        {RecordFields
            {RecordField "sum?", modifiable? = false, domain = bool, default-value = false},
            {RecordField "title", domain = String, caption = "項目"},
            {RecordField "1", domain = String, caption = "1月"},
            {RecordField "2", domain = String, caption = "2月"},
            {RecordField "3", domain = String, caption = "3月"},
            {RecordField "4", domain = String, caption = "4月"},
            {RecordField "5", domain = String, caption = "5月"},
            {RecordField "6", domain = String, caption = "6月"},
            {RecordField "7", domain = String, caption = "7月"},
            {RecordField "8", domain = String, caption = "8月"},
            {RecordField "9", domain = String, caption = "9月"},
            {RecordField "10", domain = String, caption = "10月"},
            {RecordField "11", domain = String, caption = "11月"},
            {RecordField "12", domain = String, caption = "12月"}
        }
    let rs:RecordSet = {RecordSet rfs }
    def rg = {RecordGrid width = 5in}
    set rg.record-source = rs
    {for i:int = 0 to 50 do
        def r1 = {rs.new-record}
        {rs.append r1}
    }
    ||合計計算
    {rs.add-event-handler
        {on e:RecordModified do
            {if-non-null rf = e.field then
                {if rf.name != "sum?" then
                let sum:int = 0
                {for r in rs do
                    {if r["sum?"] != true then
                        def s = {String r[rf.name] }
                        set sum = sum + {s.to-int}
                    }
                }
                {if-non-null sum-r =
                    {rs.select-one
                        filter =
                            {RecordFilter
                                {proc {r:Record}:bool
                                    {if r["sum?"] == true then
                                        {return true}
                                    }
                                    {return false}
                                 }
                            }
                    } then
                    set sum-r[rf.name] = {String sum}
                }
            }
            }
        }
    }
    ||合計行を最上行として表示
    def r = {rs.new-record}
    set r["sum?"] = true
    {rs.append r}
    {rs.commit}
    set rg.frozen-row-count =  1
    set rg.sort = "sum?"
    ||合計行を入力不可にする
    def sum-r-idx:int = 0
    {for col:int = 0 below rg.columns.size do
        {if-non-null cell = {rg.ui.get-cell-at-index sum-r-idx, col} then
            set cell.editable? = false
        }
    }
    rg
}




RE: 合計行の表示 - umemura - 05-15-2013

合計行専用のグリッドを別に作成し、入力用グリッドの下に表示するようにしてみました。
行列の固定時に同期する機能は未実装です。
依然としてスクロールバーを同期させる方法が怪しいですが。


Code:
{import * from COM.CURL.SONNTAG.LIB}
{define-proc public {get-grid-hscroll grid:RecordGrid}:#Scrollbar
    let hscroll:#Scrollbar = null
    {walk-graphics
        grid,
        ensure-ui-generated? = true,
        {proc {g:Graphic}:void
            {type-switch g
             case sb:Scrollbar do
                {if sb.direction == Orientation.horizontal then
                    set hscroll = sb
                }
            }
        }
    }
    {return hscroll}
}
{def rfs =
    {RecordFields
        {RecordField "1", domain = String},
        {RecordField "2", domain = String},
        {RecordField "3", domain = String},
        {RecordField "4", domain = String},
        {RecordField "5", domain = String},
        {RecordField "6", domain = String},
        {RecordField "7", domain = String},
        {RecordField "8", domain = String},
        {RecordField "9", domain = String},
        {RecordField "10", domain = String},
        {RecordField "11", domain = String},
        {RecordField "12", domain = String}
    }
}
{let rs:RecordSet = {RecordSet rfs }}
{let sum-rs:RecordSet = {RecordSet rfs}}
{def rg =
    {RecordGrid
        record-source = rs,
        width = {make-elastic},
        display-navigation-panel? = false
    }
}
{def sum-rg =
    {RecordGrid
        editable? = false,
        record-source = sum-rs,
        width = {make-elastic},
        display-navigation-panel? = false,
        display-column-headers? = false,
        height = 30pt
    }
}
{def v =
    {View
        width = 5in, height = 5in,
        {Frame
            width = {make-elastic},
            height = {make-elastic},
            hstretch? = true,
            vstretch? = true,
            {VBox rg, sum-rg}
        }
    }
}

{do
    {v.show}
    set (rg.ui-object asa RecordGridUI ).margin = 0pt
    set (sum-rg.ui-object asa RecordGridUI ).margin = 0pt
    {for i:int = 0 to 50 do
        def r = {rs.new-record}
        {rs.append r}
    }
    {rs.commit}
    def sum-r = {sum-rs.new-record}
    {sum-rs.append sum-r}
    {sum-rs.commit}
    ||合計計算
    {rs.add-event-handler
        {on e:RecordModified do
            {if-non-null rf = e.field then
                let sum:int = 0
                {for r in rs do
                    def s = {String r[rf.name] }
                    set sum = sum + {s.to-int}
                }
                {if-non-null sum-r = {sum-rs.select-one} then
                    set sum-r[rf.name] = {String sum}
                }
            }
        }
    }
    ||スクロールバーの同期設定
    {if-non-null
        hscrl1 = {get-grid-hscroll rg},
        hscrl2 = {get-grid-hscroll sum-rg}
     then
        set hscrl1.visible? = false
        set hscrl1.parent.height = 0pt
        {hscrl1.add-event-handler
            {on e:Adjustment at s:Scrollbar do
                {hscrl2.set-scroll-value {s.get-scroll-value}}
            }
        }
        {hscrl2.add-event-handler
            {on e:Adjustment at s:Scrollbar do
                {hscrl1.set-scroll-value {s.get-scroll-value}}
            }
        }
    }
}



RE: 合計行の表示 - dyoshida - 05-16-2013

Curl External Library のWorksheet のサンプルを参考にして、Worksheet にRecordGridを
埋め込んで、その下のセルに列の合計を表示する方法を試してみました。

※マウス操作でのRecordGridの列幅の変更や列の入れ替えまで対応すると、大変そうなので、
 RecordGridのオプションで無効にしています。

※外側のWorksheetの縦スクロールバーは必要なさそうですが、縦のみ非表示にするのは
 手間がかかりそうなので未対応です

Code:
{import * from COM.CURL.EXT.WORKSHEET}

{value
    def rf =
        {RecordFields
            {RecordField "title", domain = String, caption = "項目"},
            {RecordField "jan", domain = int, caption = "1月"},
            {RecordField "feb", domain = int, caption = "2月"},
            {RecordField "mar", domain = int, caption = "3月"},
            {RecordField "apr", domain = int, caption = "4月"},
            {RecordField "may", domain = int, caption = "5月"},
            {RecordField "jun", domain = int, caption = "6月"},
            {RecordField "jul", domain = int, caption = "7月"},
            {RecordField "aug", domain = int, caption = "8月"},
            {RecordField "sep", domain = int, caption = "9月"},
            {RecordField "oct", domain = int, caption = "10月"},
            {RecordField "nov", domain = int, caption = "11月"},
            {RecordField "dec", domain = int, caption = "12月"}
        }

    def rs =
        {RecordSet
            rf,
            {RecordData
                title = "項目1",
                jan = 10, feb = 20, mar = 30, apr = 40, may = 50, jun = 60,
                jul = 70, aug = 80, sep = 90, oct = 100, nov = 110, dec = 120
            },
            {RecordData
                title = "項目2",
                jan = 11, feb = 21, mar = 31, apr = 41, may = 51, jun = 61,
                jul = 71, aug = 81, sep = 91, oct = 101, nov = 111, dec = 121
            },
            {RecordData
                title = "項目3",
                jan = 12, feb = 22, mar = 32, apr = 42, may = 52, jun = 62,
                jul = 72, aug = 82, sep = 92, oct = 102, nov = 112, dec = 122
            },
            {RecordData
                title = "項目4",
                jan = 13, feb = 23, mar = 33, apr = 43, may = 53, jun = 63,
                jul = 73, aug = 83, sep = 93, oct = 103, nov = 113, dec = 123
            },
            {RecordData
                title = "項目5",
                jan = 14, feb = 24, mar = 34, apr = 44, may = 54, jun = 64,
                jul = 74, aug = 84, sep = 94, oct = 104, nov = 114, dec = 124
            }
        }

    def rg =
        {EmbeddedRecordGrid
            record-source = rs,
            takes-focus? = true,
            region-selection-enabled? = true,
            automatic-columns? = true,
            column-movable? = false,            || 列のドラッグ移動可否(不可に設定)
            column-resizable? = false           || 列のドラッグサイズ変更可否(不可に設定)
        }

    def rds = {RecordSetDataSource rs}
    def jan-ref = {rds.get-ref "jan"}
    def feb-ref = {rds.get-ref "feb"}
    def mar-ref = {rds.get-ref "mar"}
    def apr-ref = {rds.get-ref "apr"}
    def may-ref = {rds.get-ref "may"}
    def jun-ref = {rds.get-ref "jun"}
    def jul-ref = {rds.get-ref "jul"}
    def aug-ref = {rds.get-ref "aug"}
    def sep-ref = {rds.get-ref "sep"}
    def oct-ref = {rds.get-ref "oct"}
    def nov-ref = {rds.get-ref "nov"}
    def dec-ref = {rds.get-ref "dec"}

    || 列合計を求めるプロシージャ
    def sum-proc =
      {proc {dest:DataRef, ...:DataRef}:void
            let x:int = 0
            {for v in ... do
                {if v.composite? then
                    {for y in v do
                        set x = x + (y.value asa int)
                    }
                 else
                    set x = x + (v.value asa int)
                }
            }
            set dest.value = {String x}
        }

    || 各月の合計セルのFormulaSpecを生成するプロシージャ
    def make-sum-cell-formula-spec =
        {proc {month-ref:DataRef}:FormulaSpec
            {return
                {formula-cell
                    sum-proc,
                    domain = DataSource.string-domain,
                    halign = "right",
                    background="white",
                    month-ref
                }
            }
        }

    || ワークシート
    {Worksheet
        2, rs.fields.size + 1,
        || TODO:スクロールバーのサイズを0.45cmでハードコードしている
        {widths 1cm, 1cm, 1cm, 1cm, 1cm, 1cm, 1cm, 1cm, 1cm, 1cm, 1cm, 1cm, 1cm, 0.45cm},

        default-column-width = 1cm,
        font-size = rg.font-size,
        font-family = rg.font-family,
        grid-line-color = "gray", ||rg.grid-line-color,

        || RecordGrid本体
        row = 0, col = 0,
        row-height = 3cm, colspan = rs.fields.size + 1,
        rg,

        || 合計行
        row = 1, col = 0,
        {value-cell
            {bold 合計},
            background="white",
            valign = "center",
            font-size = rg.font-size,
            font-family = rg.font-family
        },
        row = 1, col = 1,
        {make-sum-cell-formula-spec  jan-ref},
        row = 1, col = 2,
        {make-sum-cell-formula-spec feb-ref},
        row = 1, col = 3,
        {make-sum-cell-formula-spec mar-ref},
        row = 1, col = 4,
        {make-sum-cell-formula-spec apr-ref},
        row = 1, col = 5,
        {make-sum-cell-formula-spec may-ref},
        row = 1, col = 6,
        {make-sum-cell-formula-spec jun-ref},
        row = 1, col = 7,
        {make-sum-cell-formula-spec jul-ref},
        row = 1, col = 8,
        {make-sum-cell-formula-spec aug-ref},
        row = 1, col = 9,
        {make-sum-cell-formula-spec sep-ref},
        row = 1, col = 10,
        {make-sum-cell-formula-spec oct-ref},
        row = 1, col = 11,
        {make-sum-cell-formula-spec nov-ref},
        row = 1, col = 12,
        {make-sum-cell-formula-spec dec-ref}
    }
}