How to use Axlsx:NumFmt? - ruby-on-rails

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

Related

Is it possible to modify an existing style object while using axlsx in Ruby on Rails?

I am using axlsx gem to generate Excel sheets.
I have multiple styles in my Excel. One example is shown below
style1 = wb.styles.add_style(:font_name => "Arial", :sz => 10, :i => true, :fg_color => "A6A6A6")
Now, I need to write a function which will take this style (and a currency value) as a parameter. This function should just modify the fg_color (font color) to red if the currency value is negative (all the other stylings like background color, font size, italics etc should remain the same) and return the modified style.
Is it possible to achieve the same?
def get_currency_style(style, currency_value)
if currency_value < 0
new_style = <modify ONLY the font color to red in 'style' object>
else
new_style = style
end
return new_style
end
Let your style become a hash, and modify it.
def get_currency_style(style, currency_value)
if currency_value < 0
style[:fb_color] = 'red'
end
return style
end
style1 = wb.styles.add_style(get_currency_style({ font_name: "Arial", sz: 10, i: true, fg_color: "A6A6A6" }, -10))

Change text color in an Excel cell based on a specific condition - Ruby on Rails

I am using axlsx gem to generate Excel sheets in Ruby on Rails.
I have this line which adds a row to an Excel sheet
current_row = sheet.add_row [v1, v2, v3], :style => style1
Now, v1, v2 & v3 in the above code are currency values. And any of these 3 values could be a negative value as well.
Now, whichever value is negative, I would like that value to be displayed in red text font (NOT background color). If the value is positive, then the text should be in normal black color.
How can I achieve this conditional text color?
below is sample step
# first, create style
black_cell = s.add_style :bg_color => "FF", :fg_color => "00", :sz => 14, :alignment => { :horizontal=> :center }
red_cell = s.add_style :bg_color => "FF", :fg_color => "FF0000", :sz => 20, :alignment => { :horizontal=> :center }
# second create array to manage style, if many element you can do loop the array instead using v1, v2, v3
arr1 = Array.new
sv = v1 >= 0 ? black_cell : red_cell
arr1 << sv
sv = v2 >= 0 ? black_cell : red_cell
arr1 << sv
sv = v3 >= 0 ? black_cell : red_cell
arr1 << sv
# third create the row
current_row = sheet.add_row [v1, v2, v3], :style => arr1

Ruby: axlsx : How do I bold and change BG color for selected cells?

I'm using the axlsx ruby gem to create an Excel file and I can't figure out how to apply bold and background style only to the selected cells (here State Cells)
I went thru methods like col_style and row_style and add_conditional_formatting but couldn't exactly sort out, how to use it in my code or whether it is really of any help to my requirement here.
Current Data structure:
work = [ {:state=>"Texas", :details=>{}}
{:city=>"LasVegas", :details=>{"Rob"=>"Doctor", "Dino"=>"Artist"}}
{:city=>"El paso", :details=>{"Jer"=>"Journalist", "Milo"=>"Vet"}}
{:state=>"Florida", :details=>{}}
{:city=>"Miami", :details=>{"Jake"=>"Army", "Steve"=>"Retired"}}
{:city=>"Tampa", :details=>{"Cohen"=>"Teacher", "Mike"=>""}} ]
My Code snippet:
Only the Excel part
require 'axlsx'
p = Axlsx::Package.new
p.workbook.add_worksheet(:name => "Data") do |sheet|
style1 = sheet.styles.add_style(:bg_color => "EF0920", :fg_color => "FFFFFF", b:true)
style2 = sheet.styles.add_style(:bg_color => "00FF00", :fg_color => "FFFFFF", b:true)
sheet.add_row ["State", "City", "Name", "Profession"], :style => style1
work.each do |val|
sheet.add_row [ val[:state], val[:city] ]
val[:details].each do |k, v|
sheet << ["", "", k, v]
end
end
sheet.add_row
end
p.serialize 'Data.xlsx
I've tried to add an empty line between every state using sheet.add_row but it's not working. (for legibility)
Wanted to bold and apply background of gree only to the state's cells
lastly a format mismatch.
I hope I've conveyed my problem clearly and thanks in advance for any help
Current Format
Expected Format
The style method takes an array for each cell so if you do the following you will have a bold "State" field with the other cells in the row lacking styles unless added specifically:
embolden_style = style.add_style(b: true,bg_color: '78F2FF')
sheet.add_row ["State", "City", "Name", "Profession"], style: [embolden_style, nil, nil, nil]

Prawn/PDF: Multiple formats/text on one line?

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)

TCPDF Custom page size

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);

Resources