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

帳票作成について(メモリについて)

環境/言語:[Win 2000 Pro VB.NET]
分類:[.NET]

いつもお世話になっております。 (_ _)

今回は帳票作成について質問したいのですが
activereport.netを使用して帳票を作成しているのですが
6000件のデータをA4の用紙に出力するのですが(A4一枚に12件分)

(例)
 〒999-9999 顧客番号
  東京都港区〜

  山田 太郎 様

  (〜カスタママーバーコード〜)


 上記のようなものを6000件A4で500枚出力しようとしたのですが
エラーとなり ”メモリ不足です” というメッセージを拾います。
(ちなみにPCのメモリは256MBです。)
2000件ぐらいであれば正常に動作しますが3000を超えたあたりから
メモリ不足となります。
このような場合やはり 2000件ずつ小分けにして印刷するしかない
のでしょうか??? 帳票作成の場合など大量のメモリ操作につい
てわかる方がおられましたら何卒助言の方宜しくお願い致します。
こんにちは中博俊です。

どんな仕組みなのかな。DataSetかな?
どっちにしろ、6000件を一気に出せないのであれば12件ずつ出せばすむのでは?
■No10862に返信(中博俊さんの記事)
> こんにちは中博俊です。
>
> どんな仕組みなのかな。DataSetかな?
> どっちにしろ、6000件を一気に出せないのであれば12件ずつ出せばすむのでは?


↑ お返事ありがとうございます。

仕組みとしては、顧客検索画面で抽出したデータをフォーム上のスプレッドに
はります。 そして、そのスプレッドにはチェックボックスがありそのチェック
ボックスがONのものに対して印刷するのですが、基本的にスプレッドのデータ
をそのままactivereportにセットしています。

ちなみに12件づつ出せばいいというのは12件(A4 1枚分)出力をする動作を
ループで500,回せばいいということでしょうか??
何卒宜しくお願い致します。
こんにちは中です。

#ActiveReport知らないんですよね(^^

>ちなみに12件づつ出せばいいというのは12件(A4 1枚分)出力をする動作を
>ループで500,回せばいいということでしょうか??

どんなつくりかわかってませんが、6000件がだめで、2000件にすれば出るのをうまくチューニングできて6000出せても意味はないですよね?
7000で破綻するかもしれないですし。

>ループで500,回せばいいということでしょうか??

まぁforeachすれば何回ってのも意味なくなりますよね。(^^
こんにちは、じゃんぬ です。

■No10863に返信(こうさんの記事)
> 基本的にスプレッドのデータをそのままactivereportにセットしています。

えっと、Dataset か何かで渡しているのではなくて?
ActiveReports のフォームのコントロールに直接値をセット?
それでは、厳しいでしょう。
中さん じゃんぬさんお返事ありがとうございます。

>どんなつくりかわかってませんが、6000件がだめで、2000件にすれば出るのをうまくチ>ューニングできて6000出せても意味はないですよね?
>7000で破綻するかもしれないですし。

>>ループで500,回せばいいということでしょうか??

>まぁforeachすれば何回ってのも意味なくなりますよね。(^^

最初は2000件だす動作をループでやろうとおもったのですがどうもやり方
的によくないと思いやめました  (><)


じゃんぬさんお久しぶりです。
>えっと、Dataset か何かで渡しているのではなくて?
>ActiveReports のフォームのコントロールに直接値をセット?
>それでは、厳しいでしょう。

じゃぬさんのいわれるとおりdatasetでは渡してなくフォームの
コントロールに直接値をセットしています。
今mdbを使用した開発をしているのですが、印刷対象のデータを
ワークテーブルにおとしDatasetを使用してやれば解決しそう
でしょうか? 
何卒よろしくおねがいします (_ _)
こんにちは、じゃんぬ です。

■No10869に返信(こうさんの記事)
> 今mdbを使用した開発をしているのですが、印刷対象のデータを
> ワークテーブルにおとしDatasetを使用してやれば解決しそうでしょうか? 
> 何卒よろしくおねがいします (_ _)

ワークテーブルというか、一時テーブルに落とす必要はないでしょう。
いえ、落としても良いですけど。

Dataset などを使用して、ActiveReports に渡した場合、
非同期でデータを読み込みますし、適宜メモリ解放もしているようです。
(まあ、退避する場所はあるわけですが)

これにより、何件ずつ分ける必要もなくなります。
また、表示されるまでの速度はかなり改善されるでしょう。
こんにちは。ぺがらぼです。

> 今mdbを使用した開発をしているのですが、印刷対象のデータを
> ワークテーブルにおとしDatasetを使用してやれば解決しそう
> でしょうか? 

それが一番、簡単だと思うよ。
対象データを絞り込んだデータを12件分だけワークテーブルに送って、
印刷処理させるって処理をループさせればいんじゃない?
どうやるにしても、処理が遅くなったり、メモリ不足になるなんて事を考えて悩むより、
ちょちょいとコーディングした方が制御が楽だと思うよ。

ペガラボさんじゃんぬさんお返事ありがとうございます。

まずじゃんぬさんに教えていただいたデータセットをactivereportに渡して
やる方法なのですが自分は下記の方法をおこないました。

'データセットの作成
da = New OleDb.OleDbDataAdapter("select * from insatu", cn)
ds = New DataSet
da.Fill(ds, "Insatu")

上記のように抽出対象データをデータセットにセットし

rpt = New ActiveReport1
rpt.DataSource = ds
rpt.DataMember = "Insatu"
rpt.Run()

上記のように実行しています

activereportのフォーム中ではセクションで Detailの横にある
DBの絵をダブルクリックでひらき select * form insatu
を記述し、各コントロールのDataFieldに上記で取得した列を
設定しています。

こうして実行したところ、”GDIの一般的なエラー”というエラー
メッセージをだし落ちてしまいました。 データセットの方法が
悪いのでしょうか?


ペガラボさんもお返事ありがとうございます。

>対象データを絞り込んだデータを12件分だけワークテーブルに送って、
>印刷処理させるって処理をループさせればいんじゃない?

こうした場合例えば6000件で500回分のループが回るとしてその印刷要求
はきちんと待ち状態になってくれるのかどうかが少し不安なのですが、そ
の辺りもわかれば宜しくお願いします。
■No10875に返信(こうさんの記事)
> まずじゃんぬさんに教えていただいたデータセットをactivereportに渡して
> やる方法なのですが自分は下記の方法をおこないました。

OleDb で良いんですね?

    Const SQL_COMMAND As String = "SELECT * FROM INSATU"
    Const TABLE_NAME  As String = "テーブル名"

    Dim hCommand     As OleDb.OleDbCommand
    Dim hAdapter     As OleDb.OleDbAdapter
    Dim hDataset     As DataSet
    Dim hReport      As HogeHogeListReport
    Dim hFormPreview As PreviewForm

    Try '/ インスタンス化
        hCommand = New OleDb.OleDbCommand(SQL_COMMAND, hConnection)
        hAdapter = New OleDb.OleDbAdapter(hCommand)
        hDataset = New DataSet()

        '/ Dataset へ Fill する
        hAdapter.Fill(hDataset, TABLE_NAME)

        '/ 出力されるデータが存在しない場合
        If hDataset.Tables(0).Rows.Count <= 0 Then
            MessageBox.Show("出力されるデータはありましぇん")
            Return
        End If

        '/ レポートへの適用
        hReport = New HogeHogeListReport()
        hReport.DataMember = TABLE_NAME
        hReport.Run()

        '/ 印刷プレビューへの適用
        hFormPreview = New FormPreview()
        hFormPreview.SetViewerDocument(hReport.Document)
        hFormPreview.ShowDialog()

    '/ 例外発生時は通知する
    Catch ex As Exception
        MessageBox.Show(ex.ToString())
        Throw ex

    '/ 確実に Dispose する
    Finally
        If Not hFormPreview Is Nothing Then
            hFormPreview.Dispose()
        End If
             :
             :
    End Try

hFormPreview の SetViewerDocument メソッドで、
ReportViewer コントロールの Document に hReport.Document をセットします。
じゃんぬさんお世話になります。
親切に回答していただき本当にありがとうございます。

データセット作成、割り当て、実行までは理解できたのですが、
activereportに渡したあとはデータセットより値をとりだし、フォーム
に値をセットするように変えていけばいいのでしょうか??
(今はactivereportフォームのdetailの部分の横のDBのようなものを
 ダブルクリックしてレポートデータソースというところにselect文
 をかきそこで抽出したデータをわりあてています。)

 データセットにはこのような機能はあるのでしょうか??
 何度も質問してすいませんが宜しくお願いします。(_ _)
こんにちは、じゃんぬ です。

■No10877に返信(こうさんの記事)
> データセット作成、割り当て、実行までは理解できたのですが、

理解だけでなく、できたら試してみてください。
そこで何らかの問題が発生した場合はお答えします。

> activereportに渡したあとはデータセットより値をとりだし、フォーム
> に値をセットするように変えていけばいいのでしょうか??

いいえ、Report の Document に適用していますので、何もせず表示するだけで良いです。
これも試してみてください。

> データセットにはこのような機能はあるのでしょうか??

動的に Report に値を編集、またはセットしたいのでしょうか?
ActiveReports の Report は、データを Fetch した時に駆動するイベントなどが用意されております。
通常は、そちらで色々細工していくことになります。
> ぺがらぼさんもお返事ありがとうございます。
>
> >対象データを絞り込んだデータを12件分だけワークテーブルに送って、
> >印刷処理させるって処理をループさせればいんじゃない?
>
> こうした場合例えば6000件で500回分のループが回るとしてその印刷要求
> はきちんと待ち状態になってくれるのかどうかが少し不安なのですが、そ
> の辺りもわかれば宜しくお願いします。

不安なら自分で試してみましょう。
何でも人に頼りすぎです。
私たちは、自分たちの知っている知識や経験を提供してるだけであって、
テスターではありません。
じゃんぬさんぺがらぼさんお返事ありがとう
ございます。

データセットでの方法にきりかえ実行したのですがどうも
うまくいきません。(><)
プレビューで表示させた場合は"GDIの一般的なエラー"
のようなエラーがでる
プレビューなしで実行するとメモリの不足のエラーメッセージ
をひらってきます。 
やはり無理なのでしょうか???


ぺがらぼさん

>不安なら自分で試してみましょう。
>何でも人に頼りすぎです。
>私たちは、自分たちの知っている知識や経験を提供してるだけであって、
>テスターではありません。

すいません。もちろん自分でもためしているのですが他の人はどうなの
かとおもいまして、とりあえず今は一つづつ送るロジックを作成中です。
またその報告もしたいと思います.

何卒宜しくお願いします。
> ぺがらぼさん
>
> >不安なら自分で試してみましょう。
> >何でも人に頼りすぎです。
> >私たちは、自分たちの知っている知識や経験を提供してるだけであって、
> >テスターではありません。
>
> すいません。もちろん自分でもためしているのですが他の人はどうなの
> かとおもいまして、とりあえず今は一つづつ送るロジックを作成中です。
> またその報告もしたいと思います.

回答になるかどうか判らないけど、仕様的に、
「6000件のデータをA4の用紙に出力するのですが(A4一枚に12件分)」
って有りなの?
そこに突っ込む同僚や上司とかいないの?
しかもmdbファイルだよね?
まぁ、タックシールを作る為にAccessを利用する事になったんだろうけど...
こんにちは、じゃんぬ です。

■No10881に返信(こうさんの記事)
> データセットでの方法にきりかえ実行したのですがどうもうまくいきません。(><)

「どこで」うまくいかないのですか?
場所を特定できるのは、こうさんしかいないんですよ?

> プレビューで表示させた場合は"GDIの一般的なエラー" のようなエラーがでる

こうさんにしか見れないメッセージについて、「〜のような」はないでしょう。
あたしは、精一杯回答しているので、こうさんも精一杯の情報を提供してください。
一緒に、問題を解決しようという気持ちがあたしにあっても、これでは何も解決はできません。
時間だけが無駄にすぎていきます。

Run メソッドあたりで起きると予測していますが、もしそうであれば、帳票を見直してください。
フィールドのメンバとか色々です。

> プレビューなしで実行するとメモリの不足のエラーメッセージをひらってきます。 

これも、場所の特定をしてください。
Dataset を Fill した時点なのか、それとも、もっと前なのか。
■No10882に返信(ぺがらぼさんの記事)
>>ぺがらぼさん
>>
>>>不安なら自分で試してみましょう。
>>>何でも人に頼りすぎです。
>>>私たちは、自分たちの知っている知識や経験を提供してるだけであって、
>>>テスターではありません。
>>
>>すいません。もちろん自分でもためしているのですが他の人はどうなの
>>かとおもいまして、とりあえず今は一つづつ送るロジックを作成中です。
>>またその報告もしたいと思います.
>
> 回答になるかどうか判らないけど、仕様的に、
> 「6000件のデータをA4の用紙に出力するのですが(A4一枚に12件分)」
> って有りなの?
> そこに突っ込む同僚や上司とかいないの?
> しかもmdbファイルだよね?
> まぁ、タックシールを作る為にAccessを利用する事になったんだろうけど...

ぺがらぼさん さっそくお返事ありがとうございます。

> 「6000件のデータをA4の用紙に出力するのですが(A4一枚に12件分)」
> って有りなの?

基本的にはこんな処理はしないのでしょうか??
何分まだ駆け出しのものでご教授お願いします。

> そこに突っ込む同僚や上司とかいないの?
すいません。 一応上司の指示ではあるんですが
やっぱり仕様的におかしいんですか??

ぺがらぼさんならやはり一枚ずつの処理をループ
させる方法でやるのでしょうか??

なんだかいろいろ聞いてしまって本当に申し訳
ありません。(_ _)
2005/05/21(Sat) 02:00:57 編集(投稿者)

>>「6000件のデータをA4の用紙に出力するのですが(A4一枚に12件分)」
>>って有りなの?
>
> 基本的にはこんな処理はしないのでしょうか??
> 何分まだ駆け出しのものでご教授お願いします。
>
>>そこに突っ込む同僚や上司とかいないの?
> すいません。 一応上司の指示ではあるんですが
> やっぱり仕様的におかしいんですか??
>
> ぺがらぼさんならやはり一枚ずつの処理をループ
> させる方法でやるのでしょうか??
> なんだかいろいろ聞いてしまって本当に申し訳ありません。(_ _)

可笑しいかどうかを判定するのは、俺では無いよ。
エンドユーザー。
エンドユーザーをどんなに説得しても、全てのタックシールを印刷するんだ!!
って主張してやまないなら、しょうがない。
ただ、提案ぐらいはできるよね?
じゃんぬさんぺがらぼさん何回もお返事ありがとうございます。

>こうさんにしか見れないメッセージについて、「〜のような」はないでしょう。
>あたしは、精一杯回答しているので、こうさんも精一杯の情報を提供してください。
>一緒に、問題を解決しようという気持ちがあたしにあっても、これでは何も解決はでき >ません。
>時間だけが無駄にすぎていきます。

じゃんぬさんが精一杯回答してくださるのにあいまいな発言
本当に申し訳ないです。 これからは精一杯の情報を提供
したいと思います。

とりあえずこれまでの経過をすこしまとめてみます。
@まずデータセットに対象抽出データ6000件を取り込む
Aactivereportのdatasourceとdatamemberにデータセット
 をわりあてる
Brpt.runで実行する
*上記までは何回やってもうまくいっています。

Cプレビューで表示させようとした場合 + そのまま印刷する場合

>Run メソッドあたりで起きると予測していますが、もしそうであれば、帳票を見直して >ください。
>フィールドのメンバとか色々です。

まさにじゃんぬさんのおっしゃるとおりです。 両方ともrunの部分のtry catchで
ひっかかっています。 

またこれから検証し詳しい情報を書き込みます。

何度も何度も本当にありがとうございます。

こう
  
大変遅くなって申し訳ありませんが結果報告の方を
させて頂きたいと思います。

> プレビューで表示させた場合は"GDIの一般的なエラー" のようなエラーがでる

まずこのエラーについてですが、Activereport.netのバージョンが初期の物は
カスタマーバーコード作成時にエラーとなってしまうバグがあるというのを
インターネットで発見しました。 新しいバージョンにして解決しました。

>データセットに対象抽出データ6000件を取り込む

上記の方法ではどうしてもメモリ不足となってしまうので(rpt.Run)のイベント
内でおきている模様 データセットにデータを取ってくる際のSQLを300件ずつ
とってくるようにしてそれを20回ループさせるような処理に変更し対応しました。

今回はじゃんぬさんやぺがらぼさんに大変おせわになりました。
本当にありがとうございました。

こう
解決済み!

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