Multiple tables on one page with prawn - ruby-on-rails

I'm using prawn for pdf generation and everything works quite well, but now I'm having a bit of a problem.
When I put multiple tables on one page, they just get put over each other and not under each other.
Is this normal behaviour and what can I do about it?
I add the tables on the most normal behaviour btw :)
Thanks!

What is the code you're using to create the PDF document with Prawn?
Without that, I'm guessing that you need to use 'bounding boxes' to seperate the different sections / tables in your document. Each bounding box is an area for content rendering, and new bounding boxes or text is rendered below that. See bounding_box() documentation or the example below:
> pdf.bounding_box([100,500], :width => 100, :height => 300) do
> pdf.text "This text will flow in a very narrow box starting" +
> "from [100,500]. The pointer will then be moved to [100,200]" +
> "and return to the margin_box"
> end

Related

How to create fixed footer/header with PDFKit in rails?

I'm using https://github.com/pdfkit/pdfkit in rails to generate a PDF.
kit = PDFKit.new(html)
kit.stylesheets << 'app/assets/stylesheets/pdf.css'
kit.to_pdf
The PDF renders properly based on the HTML. I'm just curious how to introduce a fixed footer/header. For instance, if I like to add a page number fixed at the bottom of the page along with a logo on every single page.
Thanks in advance.
I just dug into the gem more and saw the :header_center option.
Looks like I'll be able to pass in value (probably a template as well) when creating the PDF like so.
kit = PDFKit.new(html, :header_center => "foo", :footer_center => "bar")

Repeater in Prawn PDF rendering contents twice

I have a pdf being generated by prawn, it contains a header, a table and a footer. Both header and footer are repeatable, with :dynamic => true, the table is not.
The problem I'm having is that all content on the header and footer is displaying as if it's being rendered twice in the same place, and this seems to mess with the anti aliasing function so the text appears to be choppy and bold (see image below). However, when I zoom in or print it, it looks right.
Here's some code of the specific part where I start the repeater blocks:
pdf = Prawn::Document.new :page_size => "A4", :margin => [28, 20, 7, 20]
(...)
pdf.repeat :all, :dynamic => true do
pdf.bounding_box([0, 803], :width => 555, :height => 60) do
pdf.stroke_bounds
(...)
end
end
(...)
pdf.render
# End of file
As far as I know, this is the default way to declare a repeater block, I almost mirrorred it from the manual.
Here's the image: the top container is the header, inside the repeater, it looks like everything is bold, but it's the exact same font and line width as the section below, which is from the table, and looks fine. Sorry I can't post a larger part of the pdf, it's for confidentiality reasons.
If I remove the repeater, the header will look correct, as it should, but when I add it again it looks like this.
Has anyone else encountered this issue before? How do I fix it?
EDIT: Added some more code above. Also added the code below, which is inside a Rails template file, "historico.pdf.prawn", and this is how I call it on the controller to render the PDF and return it to the user:
rendered_pdf = render_to_string :template => "reports/historico.pdf"
send_data rendered_pdf, :filename => "Historico.pdf", :type => "application/pdf"
When you use pdf.repeat :all the pdf is 'reopened' after the document is already created and the data within the repeat block is added. This can cause a myriad of odd behavior, I believe this is what is causing your issue.
There is a related issue with a solution that utilizes Prawn's canvas method. If you adapt this solution to your problem (use canvas to generate your header and footer, rather than repeat :all) , you should no longer have these text-on-top-of-text problems.
Note:
It may be important for you to know that Prawn has officially stated that they are, "not in a good position to support templating features (I bring this up because you appear to be creating a template), " so similar workarounds may be needed if you continue to use this tool for these types of needs. Depending on your dependance on these types of templating features, you may want to look into using a different tool.

Repeat HTML in every page generated with Wicked PDF and Rails

I'm generating PDF with the Wicked PDF gem on Ruby on Rails, but have to repeat some HTML content on every page.
What I'm trying is to use just part of the page to my main content, and use HTML to add stuff around it, in every page.
Something like this image (Check)
I tried playing with header, but I wasn't able to put the content in front of the HTML (even using z-index), and was only able to position the main content with margin and spacing vertically (didn't find any options to do it horizontally).
Any ideas? Thanks!
Since no one answered, I will post my solution here. It is not beautiful nor brilliant, it is so so so far from these - but since no one answered, maybe we can start a discussion from it.
I was able to generate a PDF with only the text (but with the correct margins), with no background, using Wicked PDF. Like this image. I used it to just save the file.
This was the code for it:
# Save PDF with only the text (with correct margins)
render :pdf => "text#{id}",
:margin => {:top => "1.6in", :left => "4.1in", :right => "1.2in", :bottom => "2.5in"},
:page_size => "Letter",
:template => "careers/job_pdf_text.pdf.erb",
:save_to_file => Rails.root.join('public/job_pdf_tempfiles', "text#{id}.pdf"),
:save_only => true,
:no_background => true
Then I used RMagick to create images from this saved PDF. The important here is that I saved GIFs with transparent background, and Magick creates one image for each page on the PDF. This was the code to save the images:
# Save images from the only-text PDF
#text_images = []
text_images_magick = Magick::Image.read(Rails.root.join('public/job_pdf_tempfiles', "text#{id}.pdf"))
text_images_magick.each_with_index do |image, index|
file_name = Rails.root.join('app/assets/images/careers_pdf', "text#{id}-#{index}.gif")
image.write(file_name)
#text_images << file_name
end
Ok, so at this moment I have images of the text, like this. Now what I did was put those in an HTML page, in the correct place and then used Wicked PDF again to render the final PDF. I rendered the PDF with margin 0, and for each #text_images I created a container, from which I positioned everything else (including the image itself) to achieve what I wanted in the beggining.
Does anyone have a better idea to share?

Orchard CMS Recent Blog Post Widget Alternate View

I'm new to Orchard CMS and MVC so please forgive my ignorance. I've done a search and not found anything apparently relevant....
In one of the Footer Quad zone on my Orchard site I want to show the 5 most recent blog posts, just by title. At present it show the title, post, tags etc all in their unformatted state(Ive not style the blog yet).
Using the tracing tool I've created an alternate view called;
Parts.Blogs.RecentBlogPosts
However the only content in this view is;
#Display(Model.ContentItems)
Which -unlike other installed widgets Ive edited alternate views for- doesn't give me anything to play around with to create the layout I'm needing to create.
Have I selected the wrong shape / view, or do I need to get stuck in with some coding???
As I say, I'm new to both MVC and Orchard but very keen to learn. Any help on this will, as always, be greatly appreciated.
I got the exact same problem while trying to differentiate recent blog posts layout from blog summary posts. I followed this concept
http://weblogs.asp.net/bleroy/archive/2011/07/31/so-you-don-t-want-to-use-placement-info.aspx
and created Parts.Blogs.RecentBlogPosts alternate. Then while navigating through the model using shape tracing tool I found all elements I was looking for and put them in my new shape. I know that my approach might not be the most appropriate one but it works. Maybe it would be a starting point for someone who would need to do similar thing:
<div class="last-news">
<ul>
#foreach (var item in Model.ContentItems.ContentItems.Items)
{
var max = (item.ContentItem.BodyPart.Text.Length > 100) ? 100 : item.ContentItem.BodyPart.Text.Length;
<li><header>#Display(item.ContentItem.CommonPart.PublishedUtc.ToShortDateString())</header></li>
<li><h1>#Display(item.ContentItem.TitlePart.Title)</h1></li>
<li>#Display(Html.Raw(item.ContentItem.BodyPart.Text.Substring(0, max)))</li>
}
</ul>
</div>
It does deserve an explanation. Model.ContentItems here really is a List shape. When you call Display with it, it will locate the most appropriate template for a list shape (and that can be an alternate) and renders it. The default List rendering just renders UL/LI and in each LI calls Display on the individual Content shape for the list element, but with the Summary display type. When that in turn gets rendered, the system locates the most relevant Content template, which usually renders a bunch of zones, inside of which the parts get pushed according to placement. So there is a lot going on, in quite a few nested levels.
Still, it is possible to override the whole thing at any level. The difficulty is to know what to put there. The easiest for this is to explore the Model in shape tracing and see what you can use.
This article shows how to override list rendering in a particular situation and take it over entirely:
http://weblogs.asp.net/bleroy/archive/2011/03/27/taking-over-list-rendering-in-orchard.aspx
The Parts.Blogs.RecentBlogPosts view displays Parts_Blogs_BlogPost_List shape (Parts.Blogs.BlogPost.List.cshtml) which displays BlogPost content items. (You can see it in RecentBlogPostsPartDriver.cs). BlogPost content type consists of TitlePart and BodyPart parts which has their own shapes and views (or templates in Orchard terminology).
So to make some corrections for those templates you could try to alternate Parts_Blogs_BlogPost_List, Parts_Common_Body_Summary and other shapes.
Please see the following instructions on Orchard docs page especially:
Alternates
Accessing and Rendering Shapes

Can prawn generate PDFs with links?

I need to embed a link into a generated pdf in a ruby on rails app. Is there a way to do this with prawn?
Reading about this it turns out that prawn-format was the answer for awhile, but 0.7.x broke this.
prawn-format uses the link_annotate(rect, options={}) function to create links. What options need to be passed into this to get it to create a link in the PDF?
edit:
I would like to see a code example of this being done if anyone has one.
I know this is an old question, but for those still stumbling upon it, in current versions of Prawn, you can use inline format like this:
pdf.text "Website: <link href='http://www.stackoverflow.com'>stackoverflow</link>", :inline_format => true
If you are attempting to create a link to an external page (http://google.com), for instance you could use the following, to place a link that is 100x100 and placed at 5, 5 from the bottom left of the page, with a 1px border:
pdf.link_annotation([100, 100, 5, 5], :Border => [0,0,1], :A => { :Type => :Action, :S => :URI, :URI => Prawn::LiteralString.new("http://google.com") } )
Prawn Format would parse the text passed to the pdf.text method and find html a tags. It would then use regular expressions to parse out the target and link text and finally create a link like the one above with a bounding box (the first param) that would fit around the text that was within the tags. I'm not sure how you could achieve this without Prawn Format. But that is how you can create a link using link_annotation.
As of Prawn 0.7, prawn-format is
completely unsupported, and will not
work with versions of Prawn 0.7+. Feel
free to fork and fix, of course
- prawn-format's homepage on github
The other option is to use prawn's built in low-level annotation support:
http://prawn.majesticseacreature.com/docs/prawn-core/classes/Prawn/Document/Annotations.html#M000158
Heres the method:
link_annotation(rect, options={})
A convenience method for creating Link
annotations. rect must be an array of
four numbers, describing the bounds of
the annotation. The options hash
should include either :Dest
(describing the target destination,
usually as a string that has been
recorded in the document‘s Dests
tree), or :A (describing an action to
perform on clicking the link), or :PA
(for describing a URL to link to).
I recently did it like this - works great:
formatted_text_box([{:text=>"Google", :link=>"https://google.com", :color=>"0000ee"}])

Resources