将一个JSON文件转换成PDF。

huangapple go评论123阅读模式
英文:

Transform a json file into a pdf

问题

你应该将一个JSON文件转换为PDF。我在创建一个表格时遇到了困难,这个表格可以自动换行过长的项目,而不会溢出到右侧。

以下是你提供的JSON代码和Python实现:

  1. import json
  2. from fpdf import FPDF
  3. import pandas as pd
  4. with open('input.json') as f:
  5. data = json.load(f)
  6. pdf = FPDF()
  7. pdf.add_page()
  8. pdf.set_font('Arial', 'B', 16)
  9. # 标题
  10. pdf.cell(0, 10, '检查摘要', 0, 1)
  11. pdf.set_font('Arial', '', 12)
  12. df = pd.DataFrame(data['allIssues'])
  13. df = df[['ruleId', 'description', 'help', 'impact', 'selector', 'summary', 'source']]
  14. col_width = pdf.w / 2.2
  15. row_height = pdf.font_size * 2
  16. for issue in df.itertuples(index=False):
  17. data = [
  18. ['ruleId:', str(issue.ruleId)],
  19. ['description:', issue.description],
  20. ['help:', issue.help],
  21. ['impact:', issue.impact],
  22. ['selector:', issue.selector],
  23. ['summary:', issue.summary],
  24. ['source:', issue.source],
  25. ]
  26. # 绘制表格
  27. for row in data:
  28. pdf.multi_cell(col_width, row_height, str(row[0]), border=0)
  29. pdf.multi_cell(col_width, row_height, str(row[1]), border=0)
  30. pdf.ln(row_height)
  31. # 在表格之间绘制线
  32. pdf.line(10, pdf.get_y(), pdf.w - 10, pdf.get_y())
  33. pdf.ln(row_height)
  34. pdf.output('output.pdf', 'F')

你的实现中似乎有一个问题,导致文本溢出。要解决这个问题,你可以使用MultiCell方法来处理文本的自动换行,而不是MultiCell方法。在MultiCell方法中,你可以设置一个最大宽度,以确保文本自动换行。

要实现你想要的效果,可以尝试使用以下代码替换你的循环部分:

  1. # Draw table
  2. for row in data:
  3. pdf.multi_cell(col_width, row_height, str(row[0]), border=0)
  4. pdf.multi_cell(col_width, row_height, str(row[1]), border=0)
  5. pdf.ln()

这应该允许文本自动换行并防止溢出到右侧。这样应该更接近你期望的效果。

希望这能帮助你实现你想要的PDF输出。

英文:

I should transform a json file into pdf. I'm having trouble creating a table that allows me to make items that are too long wrap automatically and not overflow to the right side.
I paste an example of the json code that I should transform into pdf and then my implementation in python (which unfortunately returns a bad result)

json code:

  1. "allIssues":[
  2. {
  3. "ruleId":"name",
  4. "description":"Description123",
  5. "help":"Description234",
  6. "impact":"critical",
  7. "selector":[
  8. "abc1234"
  9. ],
  10. "summary":"long text",
  11. "source":"long text2",
  12. },
  13. {
  14. ...
  15. },
  16. ]

My python implementation:

  1. import json
  2. from fpdf import FPDF
  3. import pandas as pd
  4. with open('input.json') as f:
  5. data = json.load(f)
  6. pdf = FPDF()
  7. pdf.add_page()
  8. pdf.set_font('Arial', 'B', 16)
  9. # Title
  10. pdf.cell(0, 10, 'Inspection summary', 0, 1)
  11. pdf.set_font('Arial', '', 12)
  12. df = pd.DataFrame(data['allIssues'])
  13. df = df[['ruleId', 'description', 'help', 'impact', 'selector', 'summary', 'source']]
  14. col_width = pdf.w / 2.2
  15. row_height = pdf.font_size * 2
  16. for issue in df.itertuples(index=False):
  17. data = [
  18. ['ruleId:', str(issue.ruleId)],
  19. ['description:', issue.description],
  20. ['help:', issue.help],
  21. ['impact:', issue.impact],
  22. ['selector:', issue.selector],
  23. ['summary:', issue.summary],
  24. ['source:', issue.source],
  25. ]
  26. # Draw table
  27. for row in data:
  28. pdf.multi_cell(col_width, row_height, str(row[0]), border=0)
  29. pdf.multi_cell(col_width, row_height, str(row[1]), border=0)
  30. pdf.ln(row_height)
  31. # Draw line between tables
  32. pdf.line(10, pdf.get_y(), pdf.w - 10, pdf.get_y())
  33. pdf.ln(row_height)
  34. pdf.output('output.pdf', 'F')

This is a screenshot of the output:
将一个JSON文件转换成PDF。

This is what I'm trying to achive
将一个JSON文件转换成PDF。

Can you give me a hand? is it feasible to create something nice?

答案1

得分: 1

以下是翻译好的内容:

"There seems to be a lot of steps in your code. You could simply loop over the columns of your transposed df and export each of them to html. Append all html tables to a root html element and export with pdfkit:

  1. import json
  2. import pandas as pd
  3. import lxml.etree as et
  4. import pdfkit
  5. your_json = """{"url": "https://www.abc123.com", "extensionVersion": "4.51.0", "axeVersion": "4.6.3", "standard": "WCAG 2.1 AA", "testingStartDate": "2023-04-03T09:35:06.177Z", "testingEndDate": "2023-04-03T09:35:06.177Z", "bestPracticesEnabled": false, "issueSummary": {"critical": 2, "moderate": 0, "minor": 0, "serious": 0, "bestPractices": 0, "needsReview": 0}, "remainingTestingSummary": {"run": false}, "igtSummary": [], "failedRules": [{"name": "button-name", "count": 1, "mode": "automated"}, {"name": "select-name", "count": 1, "mode": "automated"}], "needsReview": [], "allIssues": [{"ruleId": "button-name", "description": "Ensures buttons have discernible text", "help": "Buttons must have discernible text", "helpUrl": "https://www.abc123.com", "impact": "critical", "needsReview": false, "isManual": false, "selector": [".livechat-button"], "summary": "Fix any of the following:\\n Element does not have inner text that is visible to screen readers\\n aria-label attribute does not exist or is empty\\n aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty\\n Element has no title attribute\\n Element's default semantics were not overridden with role=\\"none\\" or role=\\"presentation\\"", "source": "<button class=\\"livechat-button items-center bg-black shadow-liveChat rounded-full text-white p-2 h-12 transition-all opacity-0 pointer-events-none w-sp-48 opacity-0 pointer-events-none\\">", "tags": ["cat.name-role-value", "wcag2a", "wcag412", "section508", "section508.22.a", "ACT"], "igt": "", "shareURL": "", "createdAt": "2023-04-03T09:35:06.177Z", "testUrl": "", "testPageTitle": "ABC123", "foundBy": "ab@bc.com", "axeVersion": "4.6.3"}, {"ruleId": "select-name", "description": "Ensures select element has an accessible name", "help": "Select element must have an accessible name", "helpUrl": "https://www.abc123.com", "impact": "critical", "needsReview": false, "isManual": false, "selector": ["#plp__sortSelected"], "summary": "Fix any of the following:\\n Form element does not have an implicit (wrapped) <label>\\n Form element does not have an explicit <label>\\n aria-label attribute does not exist or is empty\\n aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty\\n Element has no title attribute\\n Element's default semantics were not overridden with role=\\"none\\" or role=\\"presentation\\"", "source": "<select class=\\"w-full absolute opacity-0 appearance-none text-value-small font-bold text-black uppercase cursor-pointer bg-transparent outline-0\\" id=\\"plp__sortSelected\\">", "tags": ["cat.forms", "wcag2a", "wcag412", "section508", "section508.22.n", "ACT"], "igt": "", "shareURL": "", "createdAt": "2023-04-03T09:35:06.177Z", "testUrl": "https://www.abc123.com", "testPageTitle": "ABC123", "foundBy": "ab@bc.com", "axeVersion": "4.6.3"}]}""""
  6. 请注意以上是代码部分不进行翻译
  7. <details>
  8. <summary>英文:</summary>
  9. There seems to be a lot of steps in your code. You could simply loop over the columns of your transposed df and export each of them to html. Append all html tables to a root html element and export with `pdfkit`:
  10. ```python
  11. import json
  12. import pandas as pd
  13. import lxml.etree as et
  14. import pdfkit
  15. your_json = &quot;&quot;&quot;{&quot;url&quot;: &quot;https://www.abc123.com&quot;, &quot;extensionVersion&quot;: &quot;4.51.0&quot;, &quot;axeVersion&quot;: &quot;4.6.3&quot;, &quot;standard&quot;: &quot;WCAG 2.1 AA&quot;, &quot;testingStartDate&quot;: &quot;2023-04-03T09:35:06.177Z&quot;, &quot;testingEndDate&quot;: &quot;2023-04-03T09:35:06.177Z&quot;, &quot;bestPracticesEnabled&quot;: false, &quot;issueSummary&quot;: {&quot;critical&quot;: 2, &quot;moderate&quot;: 0, &quot;minor&quot;: 0, &quot;serious&quot;: 0, &quot;bestPractices&quot;: 0, &quot;needsReview&quot;: 0}, &quot;remainingTestingSummary&quot;: {&quot;run&quot;: false}, &quot;igtSummary&quot;: [], &quot;failedRules&quot;: [{&quot;name&quot;: &quot;button-name&quot;, &quot;count&quot;: 1, &quot;mode&quot;: &quot;automated&quot;}, {&quot;name&quot;: &quot;select-name&quot;, &quot;count&quot;: 1, &quot;mode&quot;: &quot;automated&quot;}], &quot;needsReview&quot;: [], &quot;allIssues&quot;: [{&quot;ruleId&quot;: &quot;button-name&quot;, &quot;description&quot;: &quot;Ensures buttons have discernible text&quot;, &quot;help&quot;: &quot;Buttons must have discernible text&quot;, &quot;helpUrl&quot;: &quot;https://www.abc123.com&quot;, &quot;impact&quot;: &quot;critical&quot;, &quot;needsReview&quot;: false, &quot;isManual&quot;: false, &quot;selector&quot;: [&quot;.livechat-button&quot;], &quot;summary&quot;: &quot;Fix any of the following:\\n Element does not have inner text that is visible to screen readers\\n aria-label attribute does not exist or is empty\\n aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty\\n Element has no title attribute\\n Element&#39;s default semantics were not overridden with role=\\&quot;none\\&quot; or role=\\&quot;presentation\\&quot;&quot;, &quot;source&quot;: &quot;&lt;button class=\\&quot;livechat-button items-center bg-black shadow-liveChat rounded-full text-white p-2 h-12 transition-all opacity-0 pointer-events-none w-sp-48 opacity-0 pointer-events-none\\&quot;&gt;&quot;, &quot;tags&quot;: [&quot;cat.name-role-value&quot;, &quot;wcag2a&quot;, &quot;wcag412&quot;, &quot;section508&quot;, &quot;section508.22.a&quot;, &quot;ACT&quot;], &quot;igt&quot;: &quot;&quot;, &quot;shareURL&quot;: &quot;&quot;, &quot;createdAt&quot;: &quot;2023-04-03T09:35:06.177Z&quot;, &quot;testUrl&quot;: &quot;&quot;, &quot;testPageTitle&quot;: &quot;ABC123&quot;, &quot;foundBy&quot;: &quot;ab@bc.com&quot;, &quot;axeVersion&quot;: &quot;4.6.3&quot;}, {&quot;ruleId&quot;: &quot;select-name&quot;, &quot;description&quot;: &quot;Ensures select element has an accessible name&quot;, &quot;help&quot;: &quot;Select element must have an accessible name&quot;, &quot;helpUrl&quot;: &quot;https://www.abc123.com&quot;, &quot;impact&quot;: &quot;critical&quot;, &quot;needsReview&quot;: false, &quot;isManual&quot;: false, &quot;selector&quot;: [&quot;#plp__sortSelected&quot;], &quot;summary&quot;: &quot;Fix any of the following:\\n Form element does not have an implicit (wrapped) &lt;label&gt;\\n Form element does not have an explicit &lt;label&gt;\\n aria-label attribute does not exist or is empty\\n aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty\\n Element has no title attribute\\n Element&#39;s default semantics were not overridden with role=\\&quot;none\\&quot; or role=\\&quot;presentation\\&quot;&quot;, &quot;source&quot;: &quot;&lt;select class=\\&quot;w-full absolute opacity-0 appearance-none text-value-small font-bold text-black uppercase cursor-pointer bg-transparent outline-0\\&quot; id=\\&quot;plp__sortSelected\\&quot;&gt;&quot;, &quot;tags&quot;: [&quot;cat.forms&quot;, &quot;wcag2a&quot;, &quot;wcag412&quot;, &quot;section508&quot;, &quot;section508.22.n&quot;, &quot;ACT&quot;], &quot;igt&quot;: &quot;&quot;, &quot;shareURL&quot;: &quot;&quot;, &quot;createdAt&quot;: &quot;2023-04-03T09:35:06.177Z&quot;, &quot;testUrl&quot;: &quot;https://www.abc123.com&quot;, &quot;testPageTitle&quot;: &quot;ABC123&quot;, &quot;foundBy&quot;: &quot;ab@bc.com&quot;, &quot;axeVersion&quot;: &quot;4.6.3&quot;}]}&quot;&quot;&quot;
  16. data = json.loads(your_json)
  17. ## replace the above lines with the following in your case
  18. # with open(&#39;your_file.json&#39;, &#39;r&#39;) as f:
  19. # data = json.load(f)
  20. html = et.Element(&quot;html&quot;)
  21. # general info
  22. html.append(et.fromstring(f&quot;&quot;&quot;&lt;h3&gt;Site link: &lt;a href=&quot;{data[&#39;url&#39;]}&quot;&gt;{data[&#39;url&#39;]}&lt;/a&gt;&lt;/h3&gt;&quot;&quot;&quot;))
  23. html.append(et.fromstring(f&quot;&quot;&quot;&lt;h4&gt;Date: {data[&#39;testingEndDate&#39;]}&lt;/h4&gt;&quot;&quot;&quot;))
  24. html.append(et.fromstring(f&quot;&quot;&quot;&lt;h4&gt;Summary:&lt;/h4&gt;&quot;&quot;&quot;))
  25. # summary table
  26. summary = pd.Series(data[&#39;issueSummary&#39;])
  27. summary_table = et.fromstring(summary.to_frame().to_html(header=False))
  28. summary_table.set(&#39;class&#39;, &#39;summary&#39;)
  29. html.append(summary_table)
  30. # issue tables
  31. cols_of_interest = [&#39;ruleId&#39;, &#39;description&#39;, &#39;help&#39;, &#39;impact&#39;, &#39;selector&#39;, &#39;summary&#39;, &#39;source&#39;]
  32. df = pd.DataFrame(data[&#39;allIssues&#39;])[cols_of_interest].T
  33. for col in df.columns:
  34. table = et.fromstring(df[[col]].to_html(header=False))
  35. table.set(&#39;class&#39;, &#39;issue&#39;)
  36. html.append(table)
  37. html.append(et.fromstring(&#39;&lt;br/&gt;&#39;))
  38. pdfkit.from_string(et.tostring(html, encoding=&quot;unicode&quot;), &quot;./output.pdf&quot;, css=&#39;style.css&#39;)

With the following css file:

  1. /* style.css */
  2. * {
  3. font-family: &#39;Liberation Sans&#39;;
  4. }
  5. table {
  6. margin: 20px;
  7. margin-left: auto;
  8. margin-right: auto;
  9. }
  10. table.summary {
  11. width: 50%;
  12. }
  13. table.issue{
  14. border: 0;
  15. width: 100%;
  16. border-collapse: collapse;
  17. }
  18. table.issue td,
  19. table.issue th {
  20. border: 0;
  21. text-align: left;
  22. padding: 5px;
  23. }
  24. table.issue tr {
  25. border-bottom: 1px solid #dddddd;
  26. }

You'll get:

将一个JSON文件转换成PDF。

Edit: updated json with the data you provided + exporting additional data + improved css

Note: you will need to install wkhtmltopdf and make sure that it is in your path.

Edit2: limiting output to desired fields

答案2

得分: 0

免责声明: 我是这个答案中使用的 borb 库的作者。

假设您的数据如下所示:

  1. data = [
  2. {
  3. "ruleId":"name",
  4. "description":"Description123",
  5. "help":"Description234",
  6. "impact":"critical",
  7. "selector":[
  8. "abc1234"
  9. ],
  10. "summary":"long text",
  11. "source":"long text2",
  12. },
  13. ]

您可以运行以下代码:

  1. from borb.pdf import Document, Page, PageLayout, SingleColumnLayout, Paragraph, HexColor, Table, TableUtil
  2. from decimal import Decimal
  3. # 创建一个空文档
  4. doc: Document = Document()
  5. # 创建一个空页面
  6. page: Page = Page()
  7. doc.add_page(page)
  8. # 使用 PageLayout 来方便地添加内容
  9. layout: PageLayout = SingleColumnLayout(page)
  10. # 为每个问题生成一个表格
  11. for i, issue in enumerate(data):
  12. # 添加标题 (段落)
  13. layout.add(Paragraph("Issue %d" % i, font_size=Decimal(20), font_color=HexColor("#B5F8FE")))
  14. # 添加表格 (使用方便的 TableUtil 类)
  15. table: Table = TableUtil.from_2d_array([["Rule ID", issue.get("ruleId", "N.A.")],
  16. ["Description", issue.get("description", "N.A.")],
  17. ["Help", issue.get("help", "N.A.")],
  18. ["Impact", issue.get("impact", "N.A.")],
  19. ["Selector", str(issue.get("selector", []))],
  20. ["Summary", issue.get("summary", "N.A.")],
  21. ["Source", issue.get("source", "N.A.")],
  22. ], header_row=False, header_col=True, flexible_column_width=False)
  23. layout.add(table)
  24. # 存储为 PDF
  25. with open("output.pdf", "wb") as fh:
  26. PDF.dumps(fh, doc)

这将生成以下 PDF:

将一个JSON文件转换成PDF。

英文:

disclaimer: I am the author of borb, the library used in this answer.

Assuming your data looks like this:

  1. data = [
  2. {
  3. &quot;ruleId&quot;:&quot;name&quot;,
  4. &quot;description&quot;:&quot;Description123&quot;,
  5. &quot;help&quot;:&quot;Description234&quot;,
  6. &quot;impact&quot;:&quot;critical&quot;,
  7. &quot;selector&quot;:[
  8. &quot;abc1234&quot;
  9. ],
  10. &quot;summary&quot;:&quot;long text&quot;,
  11. &quot;source&quot;:&quot;long text2&quot;,
  12. },
  13. ]

You can run the following code:

  1. from borb.pdf import Document, Page, PageLayout, SingleColumnLayout, Paragraph, HexColor, Table, TableUtil
  2. from decimal import Decimal
  3. # create empty document
  4. doc: Document = Document()
  5. # create empty page
  6. page: Page = Page()
  7. doc.add_page(page)
  8. # use a PageLayout to be able to add things easily
  9. layout: PageLayout = SingleColumnLayout(page)
  10. # generate a Table for each issue
  11. for i, issue in enumerate(data):
  12. # add a header (Paragraph)
  13. layout.add(Paragraph(&quot;Issue %d&quot; % i, font_size=Decimal(20), font_color=HexColor(&quot;#B5F8FE&quot;)))
  14. # add a Table (using the convenient TableUtil class)
  15. table: Table = TableUtil.from_2d_array([[&quot;Rule ID&quot;, issue.get(&quot;ruleId&quot;, &quot;N.A.&quot;)],
  16. [&quot;Description&quot;, issue.get(&quot;description&quot;, &quot;N.A.&quot;)],
  17. [&quot;Help&quot;, issue.get(&quot;help&quot;, &quot;N.A.&quot;)],
  18. [&quot;Impact&quot;, issue.get(&quot;impact&quot;, &quot;N.A.&quot;)],
  19. [&quot;Selector&quot;, str(issue.get(&quot;selector&quot;, []))],
  20. [&quot;Summary&quot;, issue.get(&quot;summary&quot;, &quot;N.A.&quot;)],
  21. [&quot;Source&quot;, issue.get(&quot;source&quot;, &quot;N.A.&quot;)],
  22. ], header_row=False, header_col=True, flexible_column_width=False)
  23. layout.add(table)
  24. # store the PDF
  25. with open(&quot;output.pdf&quot;, &quot;wb&quot;) as fh:
  26. PDF.dumps(fh, doc)

This generates the following PDF:

将一个JSON文件转换成PDF。

huangapple
  • 本文由 发表于 2023年3月7日 17:28:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/75660127.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定