【问题标题】:Can WeasyPrint fit to Paper Size AutomaticallyWeasyPrint可以自动适应纸张尺寸吗
【发布时间】:2020-04-01 04:20:28
【问题描述】:

我曾经为一个使用 Prince XML 生成 PDF 的 HTML 文档的组织工作。那个组织已经解散了,我不再有权访问那个 Prince 许可证。由于我在沙发垫之间没有四个盛大,我一直在尝试使用 Wea​​syPrint 将 HTML 发票呈现为 PDF。我的 HTML 和 CSS 都非常简单,所以 Weasy 可以准确地渲染它们,但需要注意的是。我无法像在 Prince 中那样使用以下方法自动缩小页面到纸张大小:

@page {
prince-shrink-to-fit:auto;
}

在我修改整个站点的 CSS 以生成更小的文档之前,有谁知道 Weasy 是否支持任何类似的命令?

【问题讨论】:

    标签: python html css pdf weasyprint


    【解决方案1】:

    通过寻找一些想法来格式化 weasyprint 呈现的 pdf,我发现这个问题可能会回答你的问题。

    @page {
                size: Letter;
                margin: 0in 0.44in 0.2in 0.44in;
        }
    

    WeasyPrint page size wrong. (8.27in x 11.69 in)

    【讨论】:

      【解决方案2】:

      WeasyPrint 目前不支持这样的东西。 Prince’s documentation 的具体作用非常少。 “内容的宽度”是如何确定的?给定一个适当的特性规范,我可以知道添加到 WeasyPrint 会有多难。

      顺便说一句,我通常不看 StackOverflow 的 WeasyPrint 问题。写信给 WeasyPrint 的邮件列表或问题跟踪器会得到更多回复。

      【讨论】:

        【解决方案3】:

        如果您要打印 pandas DataFrame,这可能会有所帮助

        from typing import Callable
        import pandas as pd
        import weasyprint as wp
        
        
        def html_basic(df: pd.DataFrame) -> str:
            # Using df.style.render outputs an id in every cell,
            # whilst using df.to_html doesn't.
            return df.style.render()
        
        
        def write_pdf_autofit(df: pd.DataFrame,
                              preamble: str,
                              fn_df_to_html: Callable[[pd.DataFrame], str]=html_basic
                              ) -> bytes:
            template = f"""<html><body>{preamble}{{table}}</body></html>"""
        
            # Render on a very long page so that there's no pagination.
            # Width doesn't matter, because overflow is allowed on width.
            mycss = wp.CSS(string=(
                "@page longpage {\n"
                "    size: 210mm 10000mm;\n"
                "}"
                "body {\n"
                "   page: longpage;\n"
                "}\n"
            ))
        
            # Create a copy of the dataframe with a dummy final column,
            # so that we can get the position of the left side of the
            # dummy column which is the right side of the final real column.
            # Then do a test render to find the positions of stuff.
            df_tmp = df.copy()
            df_tmp['x'] = np.nan
            test_html = template.format(table=fn_df_to_html(df_tmp))
            test_render = wp.HTML(string=test_html).render(stylesheets=[mycss])
            test_page1: wp.Page = test_render.pages[0]
        
            # I'm not sure why only need to subtract one margin,
            # but seems to work.
            printable_width = test_page1.width - test_page1._page_box.margin_left
            printable_height = 11.7 * 96 - test_page1._page_box.margin_top
        
            # All the cells in the html rendered DataFrame
            # have an id so are anchors, so just find the
            # max x and y from all the anchors.
            max_x, max_y = map(max, *test_page1.anchors.values())
            zoom_pct = 1
            if max_x > printable_width or max_y > printable_height:
                zoom_pct = min([printable_width / max_x,
                                printable_height / max_y])
        
            # Increase the page size to fit the table, then
            # we will zoom out the write_pdf to fit standard page size.
            # A4 = 210mm x 297mm
            mycss = wp.CSS(string=(
                "@page scaled {\n"
                f"    size: {210 / zoom_pct}mm {297 / zoom_pct}mm;\n"
                "}"
                "body {\n"
                "   page: scaled;\n"
                "}\n"
            ))
        
            html = template.format(table=fn_df_to_html(df))
            pdf_bytes = wp.HTML(string=html).write_pdf(zoom=zoom_pct,
                                                       stylesheets=[mycss])
            return pdf_bytes
        
        
        if __name__ == "__main__":
            import numpy as np
            DF = pd.DataFrame(np.random.randint(0, 100, size=(100, 4)), columns=list('ABCD'))
            with open(r'c:\temp\x.pdf', 'wb') as f:
                f.write(write_pdf_autofit(DF, ""))
        
        

        【讨论】:

        • 问题是关于将 HTML 文档渲染为 PDF,与 Pandas 无关
        猜你喜欢
        • 2016-05-01
        • 1970-01-01
        • 2012-07-05
        • 2010-10-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多