This example on tcpdf's website shows how to use page formats like A4, A5 etc, but how do I set tcpdf to use custom sizes like 175mm x 266 mm?
Solutions appreciated.
No editing of the class is require... tcpdf doesn't accept a width/length parameter, it just accepts two lengths and determines which is which using the layout (either Portrait or Landscape)
$pageLayout = array($width, $height); // or array($height, $width)
$pdf = new TCPDF('p', 'pt', $pageLayout, true, 'UTF-8', false);
Go to /config/tcpdf_config.php and around line 117, modify the line:
define ('PDF_PAGE_FORMAT', 'A4');
by
define ('PDF_PAGE_FORMAT', 'LETTER');
It is important to put "LETTER" in uppercase, you can see all possible values in this file: tcpdf/include/tcpdf_static.php.
On the newer TCPDF version you can define the page size in multiple ways:
All standard page formats are already defined (more than 300 types).
You can simply define a page size by defining an array with 2 numbers: width, height (regardless the page orientation).
Alternatively, you can define advanced page details (MediaBox, Cropbox, BleedBox, TrimBox, ArtBox) as explained on the documentation of the setPageFormat() method at http://www.tcpdf.org.
Check also the default examples no. 28 and 60 at http://www.tcpdf.org.
The truth, now you can solve it like this.
//AddPage [P(PORTRAIT),L(LANDSCAPE)],FORMAT(A4-A5-ETC)
$pdf->AddPage('P','A5');
Source:
https://tcpdf.org/examples/example_028/
// 8.5 X 13 inches paper (8.5, 13)
// Convert inches to mm (215.9, 330.2)
$pdf = new Pdf('P', 'mm', array(215.9, 330.2), true, 'UTF-8', false);
Edit tcpdf.php and add a new page type or modify an existing type to your page size.
The above answer won't work for me, so I add my solution here - from http://www.tcpdf.org/examples/example_060.phps, change urx, ury for your purpose
// set page format (read source code documentation for further information)
// MediaBox - width = urx - llx 210 (mm), height = ury - lly = 297 (mm) this is A4
$page_format = array(
'MediaBox' => array ('llx' => 0, 'lly' => 0, 'urx' => 210, 'ury' => 297),
//'CropBox' => array ('llx' => 0, 'lly' => 0, 'urx' => 210, 'ury' => 297),
//'BleedBox' => array ('llx' => 5, 'lly' => 5, 'urx' => 205, 'ury' => 292),
//'TrimBox' => array ('llx' => 10, 'lly' => 10, 'urx' => 200, 'ury' => 287),
//'ArtBox' => array ('llx' => 15, 'lly' => 15, 'urx' => 195, 'ury' => 282),
'Dur' => 3,
'trans' => array(
'D' => 1.5,
'S' => 'Split',
'Dm' => 'V',
'M' => 'O'
),
'Rotate' => 90,
'PZ' => 1,
);
// Check the example n. 29 for viewer preferences
// add first page ---
$pdf->AddPage('P', $page_format, false, false);
Related
This is a 2 part question
A newbie to activerecord/Rails.
Once I execute the below activerecord query, I get
results = A.joins(:b).group(:id, :status).count
this result, now I want to present the results using an entity by postprocessing the output from
{[1, "action1"]=>2, [1, "action2"]=>2, [1, "action3"]=>1, [2, "action3"]=>2}
to
[{'id' => 1, 'action1' => 2, 'action2' => 2, 'action3' => 1}, {'id'=>2, 'action3' => 2, 'action1' => 0, 'action2' => 0} ]
(In the expected output's second hash, I added action1 => 0 and action2 => 0, because 0 should be default value.)
How to achieve the above output? I am unsure if the output of the query can be presented without postprocessing itself.
So far I tried
summaries.map {|k,v| {k[0] => {k[1] => v}}}.reduce {|acc, h| (acc || {}).deep_merge(h)}
need to make changes to the above map-reduce code to get expected result.
The expected response should look like the below, hence I am focussing on post processing the output of the query.
[
{ 'id' => value
'action1' => count,
'action1' => count,
'action1' => count
},
{
# same structure as above
}
]
I am trying to expose for example, only the id field in rails console but hitting the error
class klassEntity < Grape::Entity
expose :id
end
When I tried
klassEntity.represent([{'id' => 1, 'action1' => 2, 'action2' => 2, 'action3' => 1}, {'id'=>2, 'action3' => 2, 'action1' => 0, 'action2' => 0} ])
this failed with (Object doesn't support #inspect)
What am i doing wrong?
Update
I got this working by constructing a list of arrays from current output of
summaries.map {|k,v| {k[0] => {k[1] => v}}}.reduce {|acc, h| (acc || {}).deep_merge(h)}
and each array element contains a hash of symbols. This worked in rails console as well.
I am wondering if there is an optimal way to get here.
Find here an option using just the standard library.
I'm using map but with object (Enumerator#with_object) where the object is a Hash#new with a block given to get an empty hash as value to call Hash#merge! on it:
summaries = {[1, "action1"]=>2, [1, "action2"]=>2, [1, "action3"]=>1, [2, "action3"]=>2}
summaries.map.with_object(Hash.new {|h, k| h[k] = {}}){|(v, k), h| h[v.first].merge!({v.last => k})}
The result:
#=> {1=>{"action1"=>2, "action2"=>2, "action3"=>1}, 2=>{"action3"=>2}}
How do use Alxsx:NumFmt class?
I need to use this class to format currency values (positive and negative values)
I found some documentation for this class here - https://www.rubydoc.info/github/randym/axlsx/Axlsx/NumFmt
But there are no code samples available. Please help me on how to use this class.
Current Code:
currency_format_code = '$#,##0_;[Red]($#,##0_)'
#default_style = wb.styles.add_style(:format_code => currency_format_code,
:sz => 10, :font_name => "Arial",
:alignment => {:horizontal => :right})
#italics_style = wb.styles.add_style(:format_code => currency_format_code,
:sz => 10, :font_name => "Arial Narrow", :i => true,
:alignment => {:horizontal => :right})
row_style = [nil, nil, nil, #default_left_style] + ([#default_style] * 25)
sheet.add_row[nil, nil, nil, day1, day2, day3,
day4, day5, day6, day7, day8, day9,
day10, day11, day12, day13, day14,
day15, day16, day17, day18, day19,
day20, day21, day22, day23, day24,
day25], :style => row_style
I am not sure you can make this more performant than what you already have. This issue is that the style is applied to each cell in the row individually array_to_cells
Excerpt:
def array_to_cells(values, options={})
DataTypeValidator.validate :array_to_cells, Array, values
types, style, formula_values = options.delete(:types), options.delete(:style), options.delete(:formula_values)
values.each_with_index do |value, index|
options[:style] = style.is_a?(Array) ? style[index] : style if style
options[:type] = types.is_a?(Array) ? types[index] : types if types
options[:formula_value] = formula_values[index] if formula_values.is_a?(Array)
self[index] = Cell.new(self, value, options)
end
end
So as you can see it loops through all 28 cells in the row and looks up the style that should be applied for each then creates a new Cell with that style. Which is probably where the degradation is coming from.
Late to the party: To use the NumFmt numbers you add them to your style not using format_code, but the num_fmt option:
number_style = p.workbook.styles.add_style({
num_fmt: 2,
alignment: { horizontal: :center, :vertical => :center},
border: { color: "000000", style: :thin},
bg_color: "F2F2F2"
})
When I try the following code:
text "Hello "
text "World"
They render Hello on top of World instead of World right after Hello. I have some complicated formatting (highlighting, different font sizes etc) on text that I need on one line. I know that the :inline_formatting option exists but it seems this is too complicated to use that option.
I have the following code:
highlight_callback.rb:
class HighlightCallback
def initialize(options)
#color = options[:color]
#document = options[:document]
end
def render_behind(fragment)
original_color = #document.fill_color
#document.fill_color = #color
#document.fill_rectangle(fragment.top_left,
fragment.width,
fragment.height)
#document.fill_color = original_color
end
end
order.pdf.prawn:
highlight = HighlightCallback.new(:color => 'ffff00', :document => self)
#code....
text "Authorized Signature: "
formatted_text [{:text => "_" * 15, :callback => highlight }], :size => 20
which is producing the attached image. How can I get the signature line on the same level as the text?
Ruby 2.5.1
Rails 5.2.0
It's enough to change method text to text_box, i.e.:
bounding_box([0, cursor], width: 540, height: 40) do
stroke_color 'FFFF00'
stroke_bounds
date = 'Date: '
text_box date, style: :bold
text_box DateTime.now.strftime('%Y/%m/%d'), at: [bounds.left + width_of(date), cursor]
text_box "Signature ________________", align: :right
end
Example:
To place text at a exact position you can use text_box with the option :at.
You can get the width of your text with pdf.width_of(str) (use the same style optione :size etc. otherwise it will use the default settings to calculate)
I have this hash:
CARS = {"Audi" => 0,
"BMW" => 1,
...}
And this output from ActiveRecord (#top_cars):
{1=>18, 0=>17, 3=>13, 5=>10, 2=>5, 4=>1}
How do I replace the keys from #top_cars by the car names from CARS?
Thank you
EDIT:
So the desired output would be like {"BMW"=>18, "Audi"=>17, "Renault"=>13, "Mercedes"=>10, "Ford"=>5, "Porsche"=>1}
This would do the trick:
#top_cars.map {|key, value| [CARS.key(key), value]}.to_h
possible solution:
#top_cars.inject({}) {|memo, (key,value)| memo.merge(CARS.key(key) => value)}
You could merge cars with itself:
cars = { "Audi" => 0,
"Mercedes" => 1,
"Ford" => 2,
"Renault" => 3,
"BMW" => 4,
"Porsche" => 5
}
top_cars = {1=>18, 0=>17, 3=>13, 5=>10, 2=>5, 4=>1}
cars.merge(cars) { |*,n| top_cars[n] }
#=> {"Audi"=>17, "Mercedes"=>18, "Ford"=>5, "Renault"=>13, "BMW"=>1, "Porsche"=>10}
This uses the form of Hash#merge where a block is employed to determine the values of keys that are present in both hashes being merged, which here is all the keys.
This is the 2x2 table I need to generate:
r1c1 r1c2
r2c1 r2c1
----
In other words I should print the bottom border of the bottom right cell. This is my code:
show.pdf.prawn
#This is a two dimensional array:
my_array = [["r1c1","r1c2"],["r2c1",Prawn::Table::Cell.new(:text => "r2c2", :border_width => 1 , :borders => :bottom)]]
#Table
pdf.table my_array, :border_width => 0
Well, with this code I have a 2x2 table with no borders!
Has someone any tip?
Here one solution better known as workaround:
#This is a two dimensional array:
my_array = [["r1c1","r1c2"],["r2c1",Prawn::Table::Cell.new(:text => "r2c2", :border_width => 1 , :borders => [:bottom])]]
#Table
pdf.table my_array,
#:headers => ["h1","h2"],
:border_style => :underline_header
Omitting headers => ["h1","h2"] you avoid the underlined header.