DOBON.NET DOBON.NETプログラミング掲示板過去ログ

ActiveReports 項目数が可変のテーブルを表示させたい

環境/言語:[WindowsXP / VB.NET / ActiveReports]
分類:[.NET]

よろしくお願いします。

VB.net Activereports 3.0で帳票を作成したいと思います。
データソースは下記のようなテーブルです。

品名,金額,数量,備考1,備考2,備考3, ...... 備考n


これを、↓このようなフォーマットで表示したいです。

 品名 | 備考  | 金額
−−−−+−−−−−+−−−−
製品A |     |20,000
    | 備考1 |
    | 備考2 |
    | 備考3 |
    | 備考4 |
    | 備考5 |
−−−−+−−−−−+−−−−
製品B |     | 1,000
    | 備考1 |
−−−−+−−−−−+−−−−
製品C |     | 5,000
    | 備考1 |
    | 備考2 |
−−−−+−−−−−+−−−−
    |     |

備考は、NULL以外なら表示します。

この実現方法がわかりません。

一応、考えてみたのは、備考欄に
textBoxBikou1
textBoxBikou2
textBoxBikou3
.
.
.
textBoxBikou999
みたいにテキストボックスをたくさん配置して、
設定値なしなら非表示にする、という方法です。
どうも、あまり良いやり方ではないように思います。
もっとスマートな方法がありましたら、教えてください。
下手な説明ですみません。
■No28203に返信(チャタさんの記事)
> よろしくお願いします。
>
> VB.net Activereports 3.0で帳票を作成したいと思います。
> データソースは下記のようなテーブルです。
>
> 品名,金額,数量,備考1,備考2,備考3, ...... 備考n
>
>
> これを、↓このようなフォーマットで表示したいです。
>
>  品名 | 備考  | 金額
> −−−−+−−−−−+−−−−
> 製品A |     |20,000
>     | 備考1 |
>     | 備考2 |
>     | 備考3 |
>     | 備考4 |
>     | 備考5 |
> −−−−+−−−−−+−−−−
> 製品B |     | 1,000
>     | 備考1 |
> −−−−+−−−−−+−−−−
> 製品C |     | 5,000
>     | 備考1 |
>     | 備考2 |
> −−−−+−−−−−+−−−−
>     |     |
>
> 備考は、NULL以外なら表示します。
>
> この実現方法がわかりません。
>
> 一応、考えてみたのは、備考欄に
> textBoxBikou1
> textBoxBikou2
> textBoxBikou3
> .
> .
> .
> textBoxBikou999
> みたいにテキストボックスをたくさん配置して、
> 設定値なしなら非表示にする、という方法です。
> どうも、あまり良いやり方ではないように思います。
> もっとスマートな方法がありましたら、教えてください。
> 下手な説明ですみません。

グループという概念がありますので、それを使えば特に労せず図示されたレイアウトになります。

ActiveReports というか、ほとんどの帳票コンポーネントでは可変長での印字は基本ですし、グループも基本的なことです。
おまけに ActiveReports を販売している Grapecity さんはリファレンスと多くのサンプルを同梱していますので、基本的なことはそこに全部書かれています。
そちらをご参照ください。
回答ありがとうございます。

> グループという概念
グループヘッダのDataFieldを使って…ということでしょうか。
それともGROUP BY を含むSQL文を書いて、という意味ですか。
すごく初歩的な質問ですみません。
こんな感じのテーブルに対して、どうアプローチすれば良いのか
まったくわからない状態です。

 品名 | 金額 | 備考1 | 備考2 | 備考3 |……| 備考99 |
−−−−+−−−−+−−−−−+−−−−−+−−−−−+−−+−−−−−−+
製品A | 2,000 | 値下げ | 見切品 | 誤仕入 |  |      |
−−−−+−−−−+−−−−−+−−−−−+−−−−−+−−+−−−−−−+
製品B | 1,000 | セール |     |     |  |      |
−−−−+−−−−+−−−−−+−−−−−+−−−−−+−−+−−−−−−+
製品C | 5,000 | 特売品 | ワゴン |     |  |      |
−−−−+−−−−+−−−−−+−−−−−+−−−−−+−−+−−−−−−+
製品D | 3,000 | 見切品 | セール | 福袋用 |……| 過剰在庫 |
−−−−+−−−−+−−−−−+−−−−−+−−−−−+−−+−−−−−−+

ヒントだけでも教えていただけたらうれしいです。
よろしくお願いします。


■No28206に返信(じゃんぬねっとさんの記事)
> ■No28203に返信(チャタさんの記事)
>>よろしくお願いします。
>>
>>VB.net Activereports 3.0で帳票を作成したいと思います。
>>データソースは下記のようなテーブルです。
>>
>>品名,金額,数量,備考1,備考2,備考3, ...... 備考n
>>
>>
>>これを、↓このようなフォーマットで表示したいです。
>>
>> 品名 | 備考  | 金額
>>−−−−+−−−−−+−−−−
>>製品A |     |20,000
>>    | 備考1 |
>>    | 備考2 |
>>    | 備考3 |
>>    | 備考4 |
>>    | 備考5 |
>>−−−−+−−−−−+−−−−
>>製品B |     | 1,000
>>    | 備考1 |
>>−−−−+−−−−−+−−−−
>>製品C |     | 5,000
>>    | 備考1 |
>>    | 備考2 |
>>−−−−+−−−−−+−−−−
>>    |     |
>>
>>備考は、NULL以外なら表示します。
>>
>>この実現方法がわかりません。
>>
>>一応、考えてみたのは、備考欄に
>>textBoxBikou1
>>textBoxBikou2
>>textBoxBikou3
>>.
>>.
>>.
>>textBoxBikou999
>>みたいにテキストボックスをたくさん配置して、
>>設定値なしなら非表示にする、という方法です。
>>どうも、あまり良いやり方ではないように思います。
>>もっとスマートな方法がありましたら、教えてください。
>>下手な説明ですみません。
> 
> グループという概念がありますので、それを使えば特に労せず図示されたレイアウトになります。
> 
> ActiveReports というか、ほとんどの帳票コンポーネントでは可変長での印字は基本ですし、グループも基本的なことです。
> おまけに ActiveReports を販売している Grapecity さんはリファレンスと多くのサンプルを同梱していますので、基本的なことはそこに全部書かれています。
> そちらをご参照ください。
■No28208に返信(チャタさんの記事)

備考を改行で連結して1つの項目にしてしまえばいいんじゃないかな?
■No28212に返信(shuさんの記事)
> ■No28208に返信(チャタさんの記事)
>
> 備考を改行で連結して1つの項目にしてしまえばいいんじゃないかな?

shuさんありがとうございます。

連結!なるほど、考えつきませんでした。
どうしても1行ずつ表示できないようなら、
唯一の手段ということでそう提案してみようと思います。

実は、偶数行と奇数行で背景色を変えることになっているので、
1行ずつの表示のほうが都合が良いのです。
書き落としていてすみません。

もう少しトピックを続けさせてください。

ちなみに、自分で最初に書いていた

> 一応、考えてみたのは、備考欄に
> textBoxBikou1
> textBoxBikou2
> textBoxBikou3
> .
> .
> .
> textBoxBikou999
> みたいにテキストボックスをたくさん配置して、
> 設定値なしなら非表示にする、という方法です。

これは、試してみたところ、非表示にした分空間ができてしまい
見栄えが悪いため不採用を決めました。
DetailのHeightを書き換えてもうまくいきませんし…


じゃんぬねっとさんの教えてくださったグループにできれば
解決できるのでしょうか?
2011/02/23(Wed) 20:30:15 編集(投稿者)

すでに書かせて頂いてますが、同梱のリファレンスとサンプルは見たのでしょうか...
それ以上に具体的な回答は (説明が面倒ですので) できません。

具体的にこの部分がわからないというのは別ですが...
じゃんぬねっとさん
2度目の回答ありがとうございます。
最初のアドバイスにお答えしていなくてすみません。

> 同梱のリファレンスとサンプル

一通り見てみたのですが、私の問題の解決方法は見つけられませんでした。
サブレポートは背景色の問題がありますし…
週明けにもう一度、もっとよく探してみようと思います。

> 具体的にこの部分がわからないというのは別ですが...

よろしければ、最初におっしゃっていた
>> グループという概念がありますので
これについて教えてください。
具体的に、どういうことなのでしょうか?
「備考1」〜「備考n」をグループ化すれば良い
という話なのだと解釈していますが、
その手段がわからずに困っています。


■No28214に返信(じゃんぬねっとさんの記事)
> すでに書かせて頂いてますが、同梱のリファレンスとサンプルは見たのでしょうか...
> それ以上に具体的な回答は (説明が面倒ですので) できません。
>
> 具体的にこの部分がわからないというのは別ですが...
この場合、
レポートの使い方云々ではなく数可変で横並びのデータをどう後の都合が良いように取り出すかですよね。

行毎に背景色を切り替える場合はデータが行になっているのが手っ取り早い(他にも方法はありますが。)でしょうから、
テーブル上の備考のカラム数Nをデータ構造から求めた上で、ループでその個数分、
各備考を取得するSELECT文をUNIONで縦にくっつけたSQL文を作成してデータ取得するのが良いと思います。
また、「備考欄がすべて空の状況」と「備考の一つ目が商品の一行目ではなく次の行に配置されること」両方を考えると、
レポートのグループ機能は基本的に使えません。
(備考が必ず1から順に隙間なく使用される場合、少しやり方を変えてレポートのグループ機能を使用することもできます。)


細かいとこがいちいち面倒なのでコードは書きませんが、


    SELECT 商品ID,0 as sub,商品名,価格等,'' as 備考 from 表
    union

    →ここからが、Nループで作り上げる部分
    SELECT 商品ID,1 as sub,'' as 商品名,0 as 価格等,備考1 as 備考 from 表 where not(備考1 is null)
    union
    SELECT 商品ID,2 as sub,'' as 商品名,0 as 価格等,備考2 as 備考 from 表 where not(備考2 is null)
    union
    …でNまで

    ←ここまで

    order by 商品ID,sub


という感じのSQL文を作ります。(表に商品IDがないなら、商品名に読み替えてください。)
※なお、数字部分の全角・半角の変換等はReplace等適当に処理を考えてください。

ループ回数と備考項目名の後ろ側を得るためのNを求めるのは、
テーブル構造を取得するストアドにアクセスしてもよいですし、
知らなければ表にselect * from 表 where 0=1してもよいですし、
FillSchemaを利用してもよいですし、何でもよいです。
とりあえず列情報リストを得た後にそれをループしつつ名称を調べ、
「備考+数字の繰り返し」の項目で数字部分を数値化してもっとも大きかったところがNです。

先にNを求めれば、コレクション系クラスではなく単なる配列で処理可能ですし、
Nを先に求めず調べながらSQL組み立てをするなら、配列でReDim Preserveを使うかコレクション系クラスを使うかしてください。


で、レポート側では、subが0の際以外には名称や価格を表示しないように制御すればよいと思います。
■No28213に返信(チャタさんの記事)

サーバー側から取得したデータを直接渡すことしかできないのなら
こど。さんの言うようにUnionでやればいいと思いますが、
もしDatasetとかDataTableで渡せるのなら、取得したデータを
以下の用に新しいDataTableにセットしなおしてActiveReportへ渡し
品名、金額でグループ化してあげればよいのではないでしょうか。

 品名 | 金額 | 備考
−−−−+−−−−+−−−−−+
製品A | 2,000 | 値下げ |
−−−−+−−−−+−−−−−+
製品A | 2,000 | 見切品 |
−−−−+−−−−+−−−−−+
製品A | 2,000 | 誤仕入 |
−−−−+−−−−+−−−−−+
製品B | 1,000 | セール |
−−−−+−−−−+−−−−−+
製品C | 5,000 | 特売品 |
−−−−+−−−−+−−−−−+
製品C | 5,000 | ワゴン |
−−−−+−−−−+−−−−−+
製品D | 3,000 | 見切品 |
−−−−+−−−−+−−−−−+
製品D | 3,000 | セール |
−−−−+−−−−+−−−−−+
製品D | 3,000 | 福袋用 |
−−−−+−−−−+−−−−−+
製品D | 3,000 | 過剰在庫|
−−−−+−−−−+−−−−−+
こんばんは。
もちろんunionでやる必要はなく一旦受け取ったデータを後で加工する方法も確かに採れるのですが、
後からコードで加工するとSQL一回で必要な形で取得するよりほとんどの場合無駄に極端に遅いことと、
この場合加工というより結局別途新造データになるため仮で受け取るデータ領域と最終の加工データの領域とが必要で無駄だと考え、
unionを提案しました。

また、備考欄がすべて空の商品でも商品データは出力する必要があると思ったのと、
No.28203にて商品ヘッダの行と備考の先頭行が別位置であることを考慮し、
ActiveReports側でグループ機能を使用することができないと判断しました。
2011/02/21(Mon) 11:44:48 編集(投稿者)

■No28220に返信(こど。さんの記事)

> 後からコードで加工するとSQL一回で必要な形で取得するよりほとんどの場合無駄に極端に遅いことと、
> この場合加工というより結局別途新造データになるため仮で受け取るデータ領域と最終の加工データの領域とが必要で無駄だと考え、
> unionを提案しました。

unionを100個(備考が99個なので)のSelectに対して行ったらすごく遅い気がします。union allにすれば多少よくなるとは思いますが、備考すべてにインデックスがついてないと各Select文も遅くなってしまうかと思います。クライアントPCに
対する処理が大きくなるのは確かですがサーバ負荷を考えるとクライアントに頑張ってもらった方が良いかと思います。
できました!

こど。さんの方法とshuさんの方法と両方作ってみました。
どちらもうまく行きました。
おっしゃる通り処理が重くなる可能性があるので、
後日データを流して所要時間を調べるそうです。

本当に助かりました。
ありがとうございました。
解決済み!
完全に出遅れのあとがき...
今さらですので投稿を迷いましたが、謝罪したかったので投稿します。

結構な勘違いをしていました。申し訳ございません。
どう勘違いしていたか申し上げますと、

■No28203に返信(チャタさんの記事)
> textBoxBikou1
> textBoxBikou2
> textBoxBikou3
> .
> .
> .
> textBoxBikou999

ここを見て、備考データは別のテーブルにあって正規化されているのだと思っていました (さすがに備考が "999" なんてあり得ないと暗黙的に理解)。

> 品名,金額,数量,備考1,備考2,備考3, ...... 備考n

話の流れを見ると、マヂでこの「冗長なカラム」のイメージだったのですね... orz
(テーブル設計が悪い点は否めないところ...)
正規化されていれば、先頭行以降の行に備考を敷き詰めることは簡単に可能なので勘違いしていました。
見ているサンプルが見当違いなのに 「わからない」 と仰っているのだと、大変失礼な誤解をしておりました。本当に申し訳ございませんでした。

このような困ったレイアウトの場合、ActiveReports 側で解決する方法として、
SubReport (自動 Grow する設定) と DataView を使うパターンがありますが、
事前に必要な最小限の備考全データがわからないので、あまり賢いパターンではなさそうです。
結局のところ DataTable で自前で形成し直す shu さんの方法が良いと思います。

これだけでは、何ですのでついでに。

■No28213に返信(チャタさんの記事)
> 連結!なるほど、考えつきませんでした。
> どうしても1行ずつ表示できないようなら、
> 唯一の手段ということでそう提案してみようと思います。
>
> 実は、偶数行と奇数行で背景色を変えることになっているので、
> 1行ずつの表示のほうが都合が良いのです。
> 書き落としていてすみません。

備考 1 つずつの高さは一定ですので、詳細セクションに背景色のみを設定したオブジェクトを合成する方法を思いつきました。
ただ出力時のサイズ設定が面倒なのと、プリンタ ドライバに依存してズレが発生する恐れがあるので断念しました... orz

固定行の単票形式の帳票で、単純にページのアンダーレイ合成、もしくは空のグループ ヘッダをアンダーレイする方法と似ていますが、こちらの場合はセクションの高さで、ドライバの差異を吸収できるのでちょっと都合が違うのですね...

■No28220に返信(こど。さんの記事)
> また、備考欄がすべて空の商品でも商品データは出力する必要があると思ったのと、
> No.28203にて商品ヘッダの行と備考の先頭行が別位置であることを考慮し、
> ActiveReports側でグループ機能を使用することができないと判断しました。

shu さんの案 (DataTable を自前で作ることが) 前提なら、グループ ヘッダに品名と金額だけ出力して、残りは詳細セクションで出力すればできると思いますが...
ひょっとして、まだ私だけ勘違いしちゃっているでしょうか...

# ちなみに先頭行から備考を出力したい場合は、グループ ヘッダを続くセクションにアンダーレイすれば良い
解決済み!
じゃんぬねっとさん

丁寧にありがとうございます。
こちらこそ、わかりづらい説明ですみません。

おっしゃる通り、誰もが設計者をののしる
呪いのテーブルです。
使い勝手はこの上なく悪いのに、幾多の改修を経てなお
生き延びているのは何故なのか…

ともあれ、こちらの掲示板のおかげで問題が解決しました。
いただいた情報も実践してみたいと思います。

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

DOBON.NET | プログラミング道 | プログラミング掲示板