Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python WeasyPrint能否自动适应纸张大小_Python_Html_Css_Pdf_Weasyprint - Fatal编程技术网

Python WeasyPrint能否自动适应纸张大小

Python WeasyPrint能否自动适应纸张大小,python,html,css,pdf,weasyprint,Python,Html,Css,Pdf,Weasyprint,我曾经在一家使用Prince XML生成HTML文档PDF的组织工作。那家公司已经倒闭了,我再也不能使用Prince许可证了。由于沙发垫之间没有四千块钱,我一直在尝试使用WeasyPrint将HTML发票呈现为PDF格式。我的HTML和CSS都非常简单,因此Weasy准确地呈现它们没有问题,但有一点需要注意。我无法让页面自动缩小到纸张大小,就像我在prince中使用的那样: @page { prince-shrink-to-fit:auto; } 在我修改整个站点的CSS以生成更小的文档之前,

我曾经在一家使用Prince XML生成HTML文档PDF的组织工作。那家公司已经倒闭了,我再也不能使用Prince许可证了。由于沙发垫之间没有四千块钱,我一直在尝试使用WeasyPrint将HTML发票呈现为PDF格式。我的HTML和CSS都非常简单,因此Weasy准确地呈现它们没有问题,但有一点需要注意。我无法让页面自动缩小到纸张大小,就像我在prince中使用的那样:

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

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

WeasyPrint目前不支持类似的命令。关于它到底做什么的信息很少。如何确定“内容宽度”?如果有一个适当的特性规范,我可以告诉你添加到WeasyPrint有多难


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

通过四处寻找一些想法来格式化WeasyPrint提供的pdf,我发现这个问题可能会回答您的问题

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

如果您正在打印数据帧,这可能会有所帮助

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, ""))

输入import Callable
作为pd进口熊猫
导入weasyprint作为wp
def html_basic(df:pd.DataFrame)->str:
#使用df.style.render在每个单元格中输出一个id,
#而使用df.to_html则不行。
返回df.style.render()
def write_pdf_autofit(df:pd.DataFrame,
序言:str,
fn_df_to_html:Callable[[pd.DataFrame],str]=html_basic
)->字节:
template=f“”{preamble}{{table}}”“”
#在一个很长的页面上呈现,这样就没有分页了。
#宽度不重要,因为宽度允许溢出。
mycss=wp.CSS(字符串=(
“@page longpage{\n”
“尺寸:210mm 10000mm;\n”
"}"
“正文{\n”
“页面:长页面;\n”
“}\n”
))
#创建一个带有虚拟最终列的dataframe副本,
#这样我们就可以得到物体左侧的位置
#虚拟列,它是最终实列的右侧。
#然后做一个测试渲染来找到物体的位置。
df_tmp=df.copy()
df_tmp['x']=np.nan
test_html=template.format(table=fn_df_to_html(df_tmp))
test\u render=wp.HTML(string=test\u HTML).render(样式表=[mycss])
test_page1:wp.Page=test_render.pages[0]
#我不知道为什么只需要减去一个边距,
#但似乎有效。
可打印宽度=测试页面1.width-测试页面1.\u页面\u方框.页边距\u左侧
可打印高度=11.7*96-测试页面1.\u页面\u方框边距\u顶部
#html呈现数据框中的所有单元格
#有一个id所以是锚,所以只要找到
#所有锚固件的最大x和y。
max_x,max_y=map(max,*test_page1.anchors.values())
缩放pct=1
如果最大x>可打印宽度或最大y>可打印高度:
缩放比例=最小值([可打印宽度/最大值],
可打印(高度/最大值)
#增加页面大小以适应表格,然后
#我们将缩小write_pdf以适应标准页面大小。
#A4=210毫米x297毫米
mycss=wp.CSS(字符串=(
“@page scaled{\n”
f“大小:{210/zoom_pct}mm{297/zoom_pct}mm;\n”
"}"
“正文{\n”
“页面:缩放;\n”
“}\n”
))
html=template.format(table=fn_df_to_html(df))
pdf\u bytes=wp.HTML(string=HTML)。编写\u pdf(zoom=zoom\u pct,
样式表=[mycss])
返回pdf_字节
如果名称=“\uuuuu main\uuuuuuuu”:
将numpy作为np导入
DF=pd.DataFrame(np.random.randint(0,100,size=(100,4)),columns=list('ABCD'))
将open(r'c:\temp\x.pdf,'wb')作为f:
f、 写入(写入pdf自动拟合(DF,“”)

问题是如何将HTML文档呈现为PDF格式,与熊猫无关