列の幅を印刷時に変更したい

已查看 85 次
跳至第一个未读帖子

山田健一

未读,
2022年6月6日 21:13:422022/6/6
收件人 RapidReportサポート QAフォーラム
1つの .rrpt ファイルで、印刷時に列幅を変更することはできますか?
添付ファイルの左側と右側のように客先によって項目の長さが異なることを想定しています。
列の幅を印刷時に変更したい.xlsx

RapidReport

未读,
2022年6月6日 22:11:012022/6/6
收件人 RapidReportサポート QAフォーラム
列幅が異なる表をそれぞれ作成しておき、データの各行にどちらを採用するかを示す列値を含めておいて、
「生成条件」によって実行時に振り分ける、という方法があります。

サンプルをご確認ください。

2022年6月7日火曜日 10:13:42 UTC+9 山田健一:
example2022060701.zip

山田健一

未读,
2022年6月6日 23:07:092022/6/6
收件人 RapidReportサポート QAフォーラム
添付した例だと2種類だけですが、実際はかなりな種類が存在します。

                Report report = new Report(Json.Read(rrptFile));
                // --------------------------------------------
                report.ヘッダー.モデル.Left = modelLeft;
                report.ヘッダー.モデル.Width = modelWidth;
                report.明細.モデル.Left = modelLeft;
                report.明細.モデル.Width = modelWidth;
                // --------------------------------------------
                // 帳票にデータを渡します
                report.Fill(new ReportDataSource(dt));

みたいなイメージで変更できたら嬉しいなと思います。
これができれば、客先ごとにレイアウト情報をテーブルに保管しておき、
レポート定義は1種類でできます。
汎用なレポート定義を作成しておき、客先が特殊レイアウトテーブルの中にデータがあればそれを利用してレイアウト変更するイメージでいます。
このような運用はExcelを利用すれば可能ですが、RapidReportで実現できれば嬉しいです。

2022年6月7日火曜日 11:11:01 UTC+9 RapidReport:

RapidReport

未读,
2022年6月8日 02:04:462022/6/8
收件人 RapidReportサポート QAフォーラム
サイズが固定のコンテントの内容をユーザ毎に切替できればよい、のであればコンテント差し込み機能が使えるかもしれません。

または、
汎用レポート定義(base)を1つだけ用意して、ユーザ毎に必要に応じて特殊レポート定義(special)を用意しておく。
specialが存在するユーザならば、実行時に以下のような感じでbaseの内容を置き換えて利用する、というのではどうでしょう。

            var designBase = new ReportDesign(Json.Read("base.rrpt"));
            var designSpecial = new ReportDesign(Json.Read("special.rrpt"));
            {
                var detail = designBase.FindContentDesign("detail");
                detail.Desc = designSpecial.FindContentDesign("detail").Desc;
                detail.LoadDesc();
                detail.LoadSubDesc();
            }
            Report report = new Report(designBase);

2022年6月7日火曜日 12:07:09 UTC+9 山田健一:

山田健一

未读,
2022年6月8日 04:03:292022/6/8
收件人 RapidReportサポート QAフォーラム
ありがとうございます。
結構複雑なレポートなので、レポート定義は1つにしたいのです。
変更したいのはヘッダーの最下行の列名の幅と
明細行の列の幅だけなんです。

現在は「縮小して全体を表示」機能を使用していますが、フォントが小さくなった列の横に空白があったりするので、この空白列を縮めて、フォントが小さくなった列を広げれば見やすくなるだろうという発想です。

列の幅を印刷時に変更したい.xlsx
で言えば、
A列からE列が基本のレポート定義で、このレポート定義を使って
G列からK列までの体裁のレポートを印字したいのです。

列の幅を印刷時に変更したい.xlsx
は簡略化しているので、レポート定義を2つ作っても問題ないですが、いろいろな要件があり、凝ったレポート定義になっています。

デザインをfindしやすくするためにコンテントの名前を特殊なものに書き換えるのは構いません。

2022年6月8日水曜日 15:04:46 UTC+9 RapidReport:

RapidReport

未读,
2022年6月8日 04:33:192022/6/8
收件人 RapidReportサポート QAフォーラム
レイアウトの種類をいくつも用意して切り替えるのではなく、
カスタマイザを実装して要素の幅や位置をプログラムから制御してしまうのがよいのではないかと思います。
2022年6月8日水曜日 17:03:29 UTC+9 山田健一:

山田健一

未读,
2022年6月9日 10:09:412022/6/9
收件人 RapidReportサポート QAフォーラム
試してみました。
ヘッダー部分はうまくいきましたが、
明細部分のデータがないところで
ElementDesign e = elementDesigns.Find("order");
が例外になるようです。

データがなくても罫線はページいっぱいに印字するレポートなので、
この技は使えません。

別の方法を教えて下さい。

2022年6月8日水曜日 17:33:19 UTC+9 RapidReport:

山田健一

未读,
2022年6月9日 19:08:402022/6/9
收件人 RapidReportサポート QAフォーラム
例外になったのは
e.Child("layout").Put("x2", 20);
のほうかもしれません。

2022年6月9日木曜日 23:09:41 UTC+9 山田健一:

RapidReport

未读,
2022年6月9日 19:25:492022/6/9
收件人 RapidReportサポート QAフォーラム
そうだと思います。eのnullチェックをすればいけると思います。
または、コンテントの識別子のチェックを行ってみてください。

↓のサンプルで言うと、
↓のコードの部分になります。
if ("content_example".Equals(content.Design.Id))

2022年6月10日金曜日 8:08:40 UTC+9 山田健一:

山田健一

未读,
2022年6月9日 21:10:202022/6/9
收件人 RapidReportサポート QAフォーラム
e の nullチェックは行っています。それで、  e.Child("layout").Put("x2", 20);が悪いのかな、と。。。
そうなると e.Child("layout")のnullチェックだと思いますが、これで例外は回避したとしてもブランク枠の幅が変わらないので、要件を満たしません。
e.Child("layout")がnullだったときはどうやってブランク枠の幅が変えられるか教えて下さい。

2022年6月10日金曜日 8:25:49 UTC+9 RapidReport:

RapidReport

未读,
2022年6月9日 21:48:212022/6/9
收件人 RapidReportサポート QAフォーラム
eさえnullでなければ、 e.Child("layout")  ~がnull参照エラーになることはない、はずです。
仮にブランク枠(layoutが未設定)だったとしても、 
e.Child("layout")は呼ばれた時点で空のlayoutを自動的に生成する仕組みになっているので、
これがnullを返すことはありません。

↓の54行目以降の部分が、Childの実装です。

いま一度、デバッガ等を利用して、
どのオブジェクトがnullとなっているためにエラーが起きているのか
を見直していただけますでしょうか。

2022年6月10日金曜日 10:10:20 UTC+9 山田健一:

山田健一

未读,
2022年6月10日 00:39:372022/6/10
收件人 RapidReportサポート QAフォーラム
var layout = e.Child("layout");
としたところ
layout.ToString() は "()"でした。
この状態に
layout.Put("x2", 20);
をしようとして例外になっているようです。
「オブジェクト参照がオブジェクト インスタンスに設定されていません。」
例外をキャッチして無視するようにすると、データのあるところは期待通りです。
データがない枠だけのところは枠のサイズが変わらないので、凸凹な表になっています。

データがなく枠だけの状態は
if (layout.ToString().Trim().Equals("()"))
で捕まえられえそうです。問題はこのとき、どうやって、枠のレイアウトを設定するかです。
定義段階で修正したほうがわかりやすいように感じています。



2022年6月10日金曜日 10:48:21 UTC+9 RapidReport:

RapidReport

未读,
2022年6月10日 00:57:452022/6/10
收件人 RapidReportサポート QAフォーラム
うーん・・・

layout.Put("x2", 20);
↑の式が例外を発生させることは無いはずなのですが・・・
オブジェクトの生成方法に誤りがあるなどして不正な状態になっているのかもしれません。

お手数ですが、以下のことを確認していただけますか。

layout.Modify というオブジェクトが null になっていないかどうか。
このオブジェクトは通常であればnullになることは無いはず、です。

2022年6月10日金曜日 13:39:37 UTC+9 山田健一:

RapidReport

未读,
2022年6月10日 01:02:402022/6/10
收件人 RapidReportサポート QAフォーラム
もしも

e.Put("layout", null) 

というコードが実行されていると、 
layout.Modify  がnullになり、 layout.Put("x2", 20) が例外を発生させることになりそう、です。

2022年6月10日金曜日 13:57:45 UTC+9 RapidReport:

山田健一

未读,
2022年6月10日 01:39:482022/6/10
收件人 RapidReportサポート QAフォーラム
Trace.WriteLine("layout.Modify.ToString() = " + layout.Modify.ToString());
 Trace.WriteLine("layout.Modify.Count = " + layout.Modify.Count);
というコードで試しました。
layout.Modify.ToString() = System.Collections.Hashtable
layout.Modify.Count = 0
です。
nullではないですが、空ということですね。
layout.Put("x2", 20);
は例外を発生させませんでした。
ただし、枠の幅は変わらないので、このままでは要件を満たしません。

よい方法を教えて下さい。
繰り返しになりますが、定義が動的に変えられればそのほうがわかりやすいと個人的には考えています。

2022年6月10日金曜日 14:02:40 UTC+9 RapidReport:

RapidReport

未读,
2022年6月10日 02:14:512022/6/10
收件人 RapidReportサポート QAフォーラム
すみません。私が問題を理解できていない気がします。

「変更したいのはヘッダーの最下行の列名の幅と明細行の列の幅だけ」
とのことでしたので、これを実現するには要素の定義を動的に変更できるカスタマイザを紹介すればよいかと考えていました。

列(枠)の幅を変更、というのは対応する要素の幅を設定できればよい、という認識でした。
RapidReportの要素定義の仕様上、幅を直接指定することはできないのですが、
左端座標である x1 と x2 をそれぞれ指定すれば結果的に、要素の幅(および位置)を動的に変更できます。

例えば以下のような感じです。

var x = 100; // 左端位置
var w = 200; // 幅
layout.Put("x1", x);
layout.Put("x2", x + w);

これらの機能によって、「客先ごとに項目の幅を変える」ということは実現できるかと思っているのですが・・・
認識に食い違いがありましたら教えていただけますと幸いです。

2022年6月10日金曜日 14:39:48 UTC+9 山田健一:

山田健一

未读,
2022年6月10日 02:38:522022/6/10
收件人 RapidReportサポート QAフォーラム

認識に食い違いはありません。
カスタマイザーも期待どおり動作します。

ただし、作りたいのは

https://rapidreport.systembase.co.jp/tutorial1.html

で紹介されているような帳票です。

この例で言えば、
「以下余白」までは列幅が変更されます。
しかし、
「以下余白」よりあとの行、すなわち、データがなく枠だけの行になるとカスタマイザーが期待どおり動作してくれません。
layoutが()だからではないかと想像しています。

この御見積書の列幅を客先ごとに動的に変化させたいと言えばイメージは共有できると思います。
例えばある客先は数量は1桁だが、単価が高い、別の客先は数量が膨大だが単価は1円クラスと言った感じです。
御見積書程度なら動的に変更させる必要もないですが、今ターゲットにしている帳票は項目数も多いです。
2022年6月10日金曜日 15:14:51 UTC+9 RapidReport:

RapidReport

未读,
2022年6月12日 21:03:372022/6/12
收件人 RapidReportサポート QAフォーラム
データがない行でうまくいかない、のであれば原因はおそらく式にあると思います。

データがない行の場合(「空行を出力」によって出力されたコンテントの場合)、
以下のように列の値を取得する式を評価するとnullが返ります。

evaluator.EvalTry(".USERCD");

「客先ごとに変化」を行うためには、
どのようなレイアウトを採用すべきかを識別するための情報がいずれかの列に含まれていて、
これをカスタマイザから参照する必要があるのではないかと思いますが、
先に示したような現在の列値を得る式だと、データのない行では常にnullしか返ってきません。

そこで、式の後に@を付けることによって、
現在位置よりも一つ上位のグループに割り当てられた値を得ることができます。

evaluator.EvalTry(".USERCD@");

というわけなので、カスタマイザ内での式を見直していただけますでしょうか。

layoutについては、空行かどうかで動作が変わることはない(はず)ので、
これが原因とは考えにくい、と思っています。

2022年6月10日金曜日 15:38:52 UTC+9 山田健一:

山田健一

未读,
2022年6月16日 07:24:242022/6/16
收件人 RapidReportサポート QAフォーラム
evaluator.EvalTry(".USERCD@");
この方法でうまく動作しました。

ありがとうございました。

2022年6月13日月曜日 10:03:37 UTC+9 RapidReport:
回复全部
回复作者
转发
0 个新帖子