2

私が友人のビジネスのために書いているプログラムでは、reportlab モジュールを使用して、さまざまなレポート用の PDF ドキュメントを作成しています。ほとんどの場合、レポートは 1 ページに収めることができますが、まれに 2 ページにまたがることがあります。このようなまれな状況では、上下の余白を小さくしてページを再フォーマットし、1 ページに収まるかどうかを確認したいと考えています。そうでない場合は、最小限の余白を使用して、2 ページにまたがるようにします。

SimpleDocTemplateレポートを作成するために、クラスのインスタンスを作成しています。すべての flowables をbuildメソッドに渡した後、属性をクエリして、page使用されたページ数を確認できることがわかりました。最初に試したのは次のとおりです。

parts = []
path = "/path/to/my/file.pdf"
# ... a bunch of code that appends various flowables to 'parts'
doc = SimpleDocTemplate(path, pagesize=landscape(letter))
doc.build(parts)
# Shrink the margins while it's more than one page and the margins are above zero
while doc.page > 1 and not any([doc.topMargin <= 0, doc.bottomMargin <= 0]):
    # Decrease the page margins and rebuild the page
    doc.topMargin -= inch * .125
    doc.bottomMargin -= inch * .125
    doc.build(parts)
# If the margins are nil and we're still at 2 or more pages, use minimal margins
if doc.page > 1:
    doc.topMargin = inch * .25
    doc.bottomMargin = inch * .25
    doc.build(parts)

buildマージンを変更した後に同じ部分でメソッドを呼び出すと、すべてが再計算されると想定しました。しかし、多くの試行錯誤の結果parts、メソッドに渡されるリストbuildは、ビルド プロセス中に本質的に取り除かpartsれ、空のリストのままになることがわかりました。これが再度メソッドに渡されるbuildと、ゼロ ページのドキュメントが作成されました。

これを回避するために、partsリストのコピーを使用してドキュメントを作成してみました。

doc.build(parts[:])

これにより奇妙な例外が発生したため、copyモジュールを使用してディープ コピーを試みました。

doc.build(copy.deepcopy(parts))

これは例外をスローしませんでしたが、マージンも変更しませんでした。

少し必死になって、SimpleDocTemplate属性を詳しく調べたところ、 という名前のメソッドが見つかりました_calc。これでページが再計算されるのではないかと思い、余白を変えて呼び出してみました。例外はスローされませんでしたが、機能しませんでした。

私がなんとかそれを機能させる唯一の方法は、deepcopyプロセスを使用して、余白を微調整するたびに新しいドキュメントを作成することです。

doc = SimpleDocTemplate(path, pagesize=landscape(letter))
doc.build(copy.deepcopy(parts))
# Shrink the margins while it's more than one page and the margins are above zero
while doc.page > 1 and not any([doc.topMargin <= 0, doc.bottomMargin <= 0]):
    doc.topMargin -= inch * .125
    doc.bottomMargin -= inch * .125
    doc = SimpleDocTemplate(path, pagesize=landscape(letter),
                            topMargin = doc.topMargin,
                            bottomMargin = doc.bottomMargin)
    doc.build(copy.deepcopy(parts))
# If the margins are nil and we're still at 2 or more pages, use minimal margins
if doc.page > 1:
    doc.topMargin = inch * .25
    doc.bottomMargin = inch * .25
    doc = SimpleDocTemplate(path, pagesize=landscape(letter),
                            topMargin = doc.topMargin,
                            bottomMargin = doc.bottomMargin)
    doc.build(copy.deepcopy(parts))

しかし、その道を行くには多くの不必要な作業のように感じます. ドキュメントのマージンを変更し、それらの新しい値を使用してドキュメント自体を再構築するように指示したいのですが、方法がわかりません。それは可能ですか?

4

1 に答える 1

1

非常に興味深い質問です。ただし、ReportLab でこれを行う正しい方法を既に見つけたと思います。ビルド プロセスは、後戻りできない副作用が生じるため、ドキュメントに対して実行できる 1 回限りの処理です。ありがたいことに、すでにお気づきのように、多少面倒ではありますが、やりたいことを実行するのはそれほど難しくありません。

于 2013-09-24T17:45:38.520 に答える