Формирование pdf-файлов в Ruby-среде
Если почитать пару-тройку веток на ror2ru про генерацию pdf-а на руби, то можно всерьез расстроиться, решив что для бедного девелопера/заказчика с головой обычных размеров вариантов вовсе нет, ибо удобные библиотеки - платные: PDFlib, PrinceXML, а бесплатные и работающие - это только Tex.
Как выяснилось, все не так плохо.
В общем, в очередном проекте потребовалось приделать генерацию пары отчетов в pdf-формате.
Чего нам хотелось от библиотеки:
- возможность вставить картинку
- вывести текст в несколько столбцов произвольной ширины
- в идеале хотелось бы просто загнать готовый HTML, а на выходе получить PDF
- бонус в виде поддержки UTF-8 нам бы тоже не помешал
Первое, на что упал взгляд - это PDF::Writer.
Подкупила многостраничная документация (понятно сразу, что возможностей - богато) в pdf-формате (по любому автор верстал ее с помощью своей же библиотеки) плюс наличие каких-никаких примеров для старта. Опять же Ryan Bates его расхвалил в одном из скринкастов.
Что в нем хорошего - из коробки есть обработка тегов b, u, i и возможность написать свои теги и обработчики к ним.
Что плохого - вывод текста в две колонки оказался настолько нетривиальной задачей и переносы строк работали так странно, что на этом пришлось свое знакомство с этой библиотекой закончить.
Едем дальше:
PDF::HTMLDoc у меня просто не завелся
Pdfwriter - совсем уж прост:
- No image support (you can draw your own tables etc. though with lines)
- Only font supported is Times New Roman (in bold and non-bold incarnations)
C JasperReports связываться совершенно не хотелось, потому что Java
PDFlib понравился, но не подошел потому-что он free только для personal use. Если кто будет с ним разбираться, то вот вам пачка ссылок, что я наковырял.
Ну вот в общем долго-ли коротко-ли, но набрел я на ruby-порт пхпшной библиотеки FPDF - rfpdf.
Сразу говорю, эту ссылку через гуголь вы фиг найдете, большинство сайтов по запросам “ruby fpdf” и “rfpdf” ведут куда угодно, но не туда куда надо. Как сам нашел, уже и сам не знаю.
В общем, она оказалась довольно-таки пригодной к использованию и все мои потребности вполне покрыла.
Документацией можно пользоваться прямо ПХП-шной, ибо портировано один в один.
Вот наглядный пример использования, который конечно же нашелся уже после того как все было сделано.
Единственное, пара рекомендаций по code style и удобству применения.
Очень удобно для каждого шаблона сделать отдельную модель с типичными для этого шаблона методами:
user_report.rb (по клику полный листинг)
class UserRepor < FPDF
def initialize(titlename, orientation='P', unit='mm', format='Letter')
super(orientation, unit, format)
@titlename = titlename
@Y = 55
@X = 30
AddPage()
SetMargins(@X,@Y)
end
def Header()
# Page header
if PageNo()>1
SetXY(13,9)
SetFont(’Helvetica’, ”, 8)
SetTextColor(0)
Cell(0, 10, “#{@titlename} (continued)”, 0, 0, ‘L’)
SetY(20)
end
end
def Footer()
# Page footer
if PageNo()>1
SetY(-19)
SetFont(’Helvetica’, ”, 8)
SetTextColor(0)
Cell(0, 10, ‘Page ‘ + PageNo().to_s, 0, 0, ‘R’)
end
end
def SetPos
SetX(@X)
SetY(@Y)
end
def GetPos
@X = GetX()
@Y = GetY()
end
def li(text, width=140)
SetFont(@font, ”, 9)
SetFillColor(0, 81, 125)
SetPos()
Rect(@X+10, @Y+0.7, 2, 2, ‘F’)
SetX(@X+15)
MultiCell(width,4,text,0,’L',”)
Ln(1.9)
GetPos()
end
def h1(text,width=160)
Ln(3)
SetX(@X)
SetFont(@font, ‘B’, 10)
MultiCell(width, 4, text)
Ln(3)
GetPos()
end
def col1
@X=20
@Y=56
SetPos()
yield
end
def col2
@X=75
@Y=56
SetPos()
yield
end
#etc …
end
Это раз, ага. Второе - хоть всю рутину мы и прячем в методы нашего класса, код генерации PDF-a в контроллере - это не кошерно. У нас MVC все таки или как?
Складываем все в вид: report.rfpdf
<%
pdf = UserReport.new(@user.full_name)
pdf.col1 do
pdf.h1 'Заголовок'
@user.some_list.each do |item|
pdf.li item
end
end
pdf.col2 do
#a lot of content generation
end
%>
<%= pdf.output %>
Ну и в контроллер дописываем:
send_data(render_to_string(:action => 'report', :layout => false),
:filename => "report.rfpdf", :type => "application/pdf")
Вуаля.
Конечно, rfpdf - не та библиотека, у которой будет приятно поковыряться во внутренностях, ибо внутри полное торжество ПХП-стайл-программинга, но задачи оно свои решает, решает их хорошо и не требует нечеловеческих усилий для понимания того как с ним работать.
Но это еще не все. В сабвершне у проекта обнаружился порт TCPDF, который, внимание!, нормально работает с UTF-8 и умеет из коробки весьма и весьма приличную конвертацию HTML-я в PDF.
Скептикам смотреть сюда и сюда.
А вы говорите Tex..
Из замеченных минусов TCPDF - в нем на данный момент не работает вставка JPEG-картинок (с PNG работает без проблем), и больший по сравнению с RFPDF размер выходного файла.
UPD: Вот здесь мини-рецепт про то, как приклеить к отчету подложку в виде другого pdf-файла.
Tags: ruby, pdf, utf-8, unicode, html2pdf, rfpdf, fpdf, tcpdf, pdf-writer, pdflib
Комментариев: 8
Написать! | RSS | Trackback uri