Git Product home page Git Product logo

axlsx_styler's Introduction

axlsx_styler

Gem Version CI Status RubyGems Downloads

Note This gem has been merged upstream into caxlsx v3.3.0. Please remove this gem from your Gemfile when using [email protected] and above.

axlsx_styler is a gem that allows you to build clean and maintainable styles for your axlsx spreadsheets. Build your spreadsheeet with data and then apply styles later.

While axlsx is an excellent tool to build Excel spreadsheets in Ruby, the sheets styles are only applied immediately as the row is created. This makes it very difficult to style easily and effectively.

To solve this issue, axlsx_styler was born to allow the separation of styles from content within your axlsx code. It gives you the ability to fill out a spreadsheet with data and apply styles later.

Works well in any Rails app or outside of any specific Ruby framework.

Usage

This gem provides a DSL that allows you to apply styles or borders to ranges of cells.

Styles

sheet.add_style 'A1:D10', b: true, sz: 14

The styles can be overlayed, so that later on you can add another style to cells that already have styles.

sheet.add_style 'A1:D1', bg_color: 'FF0000'

Applying multiple styles as a sequence of Ruby hashes is also possible.

bold     = { b: true }
centered = { alignment: { horizontal: :center } }
sheet.add_style 'A2:D2', bold, centered

Applying a style to multiple ranges at once.

sheet.add_style ['A2:G2', "A8:G8", "A12:G12"], b: true, sz: 14

Borders

The border style is to draw a thin black border on all four edges of the selected cell range.

sheet.add_border 'B2:D5'

You can easily customize the border styles.

sheet.add_border 'B2:D5', [:bottom, :right]
sheet.add_border 'B2:D5', { edges: [:bottom, :right], style: :thick, color: 'FF0000' }

Applying border to multiple ranges at once.

sheet.add_border ['A2:G2', "A8:G8", "A12:G12"]

Example

Suppose we want create the following spreadsheet:

alt text

You can apply styles after all data is entered, similar to how you'd create an Excel document by hand.

require 'axlsx_styler'

axlsx = Axlsx::Package.new
workbook = axlsx.workbook
workbook.add_worksheet do |sheet|
  sheet.add_row
  sheet.add_row ['', 'Product', 'Category',  'Price']
  sheet.add_row ['', 'Butter', 'Dairy',      4.99]
  sheet.add_row ['', 'Bread', 'Baked Goods', 3.45]
  sheet.add_row ['', 'Broccoli', 'Produce',  2.99]
  sheet.column_widths 5, 20, 20, 20

  # using AxlsxStyler DSL
  sheet.add_style 'B2:D2', b: true
  sheet.add_style 'B2:B5', b: true
  sheet.add_style 'B2:D2', bg_color: '95AFBA'
  sheet.add_style 'B3:D5', bg_color: 'E2F89C'
  sheet.add_style 'D3:D5', alignment: { horizontal: :left }
  sheet.add_border 'B2:D5'
  sheet.add_border 'B3:D3', [:top]
end
axlsx.serialize 'grocery.xlsx'

If you try creating this same spreadsheet using only axlsx, you will find this is much more difficult. See this See this example

For more examples, please see the examples folder

Contributing

We use the appraisal gem for testing multiple versions of axlsx. Please use the following steps to test using appraisal.

  1. bundle exec appraisal install
  2. bundle exec appraisal rake test

Credits

Created by Anton Sakovich - @sakovias

Maintained by Weston Ganger - @westonganger - Uses axlsx_styler within the gem, spreadsheet_architect

axlsx_styler's People

Contributors

davefp avatar jaronson avatar johnkeith avatar sakovias avatar westonganger avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

axlsx_styler's Issues

Not compatible with rails 4

Tried installing this earlier, are there actually problems with newer versions of Rails, or is this just a dependency syntax issue?

Bundler could not find compatible versions for gem "activesupport":
  In Gemfile:
    axlsx_styler (>= 0) ruby depends on
      activesupport (~> 3.1) ruby

    rails (= 4.1.4) ruby depends on
      activesupport (4.1.4)

sheet.add_style ignores style set with sheet.add_row (ver.: 0.1.3)

wb = xlsx_package.workbook
money_eft = wb.styles.add_style format_code: '#,##0, \\eFt;-#,##0, \\eFt;- \\eFt;@'
wb.add_worksheet(name: "foo") do |sheet|
  sheet.add_row ['123456789'], style: [money_eft]
end

this results in the formatting code taking effect on the field.

wb = xlsx_package.workbook
money_eft = wb.styles.add_style format_code: '#,##0, \\eFt;-#,##0, \\eFt;- \\eFt;@'
wb.add_worksheet(name: "foo") do |sheet|
  sheet.add_row ['123456789'], style: [money_eft]
  sheet.add_style 'A1:A1', bg_color: 'FF0000'
  sheet.add_style 'A1:A1', b: true
end

this loses the format code, but applies both the background color and the bold font correctly.

apply_styles method on sheet

In my gem SpreadsheetArchitect I have the ability to create axlsx sheets individually. I was wondering if we can get the workbook.apply_styles to also be available as sheet.apply_styles so that I can apply the styling before returning the sheet.

Merging cell's border styles

Hello,

I want:
expected

My code is:

require 'axlsx_styler'
axlsx = Axlsx::Package.new
workbook = axlsx.workbook
workbook.add_worksheet do |sheet|
	sheet.add_row
	row = sheet.add_row
	row.add_cell
	cell = row.add_cell
	sheet.add_border('B2:B2', { edges: [:left, :right], style: :thick, color: 'FF0000' })
	sheet.add_border('B2:B2', { edges: [:top, :bottom], style: :double, color: '0000FF' })
end
axlsx.serialize('a.xlsx')

But i get:
found

Any idea to perform that?
Thanks!

add_border trips up on borders previously set with add_style (ver.: 0.1.3)

I am trying to draw a table with a thin grid and a medium outline:

this correctly draws the grid:

wb.add_worksheet(name: "foo") do |sheet|
  sheet.add_row ['1', '2', '3']
  sheet.add_row ['4', '5', '6']
  sheet.add_row ['7', '8', '9']
  sheet.add_style 'A1:C3', border: {style: :thin, color: '000000'}
end
wb.apply_styles

this correctly draws the outline:

wb.add_worksheet(name: "foo") do |sheet|
  sheet.add_row ['1', '2', '3']
  sheet.add_row ['4', '5', '6']
  sheet.add_row ['7', '8', '9']
  sheet.add_border 'A1:C3', style: :medium
end
wb.apply_styles

but I get an error if I try to combine the two:

wb.add_worksheet(name: "foo") do |sheet|
  sheet.add_row ['1', '2', '3']
  sheet.add_row ['4', '5', '6']
  sheet.add_row ['7', '8', '9']
  sheet.add_style 'A1:C3', border: {style: :thin, color: '000000'}
  sheet.add_border 'B2:C3', style: :medium
end
wb.apply_styles
ActionView::Template::Error (undefined method `+' for nil:NilClass)

and I get a different error if I try the other way around:

wb.add_worksheet(name: "foo") do |sheet|
  sheet.add_row ['1', '2', '3']
  sheet.add_row ['4', '5', '6']
  sheet.add_row ['7', '8', '9']
  sheet.add_border 'A1:C3', style: :medium
  sheet.add_style 'A1:C3', border: {style: :thin, color: '000000'}
end
wb.apply_styles
ActionView::Template::Error (no implicit conversion of nil into Array)

NoMethodError: undefined method `row' for nil:NilClass

I was just trying the example for adding the border:

sheet.add_border 'B2:D5', { edges: [:bottom, :right], style: :thick, color: 'FF0000' }

But, I got error:

NoMethodError: undefined method row' for nil:NilClass from /dependencies/bundle/ruby/2.3.0/gems/axlsx-2.1.0.pre/lib/axlsx/workbook/worksheet/worksheet.rb:721:in range'

Whats wrong?

Support for format_code or num_fmt

I was having no success getting a format_code or num_fmt so that I can get number and currency formats. Is this supported or do you know how we can add it?

This is my code:

sheet.add_style "B2:E5", format_code: "$#,##0.00"

undefined method `styles_applied' for nil:NilClass

Only occurring since 0.1.4. It appears that @workbook is not defined at the point of calling apply_styles. However, Axlsx::Package provides a workbook method, which returns the workbook.

Replacing @workbook with workbook corrects the issue. PR forthcoming.

Utilize this original repo via organization instead of forking

As someone who uses this project heavily in SpreadsheetArchitect, I have a few concerns about the forking of this project:

  • Forking make all the github stars go back to zero
  • Forking makes the project un-searchable
  • Forking kills all SEO

In essence, Forking is not the right answer for hand-off of development of a project/plugin.

Could we instead utilize this original repo by creating an organization? Ex. axlsx-styler-gem/axlsx_styler. This would enable future maintainers to completely the repo without any interaction from the original author and it would solve all of these issues.

Doesnt work well with custom default font

Original Thread: #14 (comment)

Problem

If a user defines this in the spreadsheet it will set the default font name

sheet.styles.fonts[0].name = 'Pontiac'

Currently alxsx_styler is not aware of this type of customization and assumes the following based on prior manual testing.

def add_style(options={})
if options[:type] == :dxf
style_id = super
else
raw_style = {type: :xf, name: 'Arial', sz: 11, family: 1}.merge(options)

Seems that we can likely just change Arial to sheet.styles.fonts[0].name

Can we also make any similar dynamic improvements to sz: 11 and/or family: 1 ?

add_style overwrites all previous styles

I had already defined row styles through plain axlsx but I was applying a column style using add_style and noticed it was overwriting all previous styles.

Is there any way we can get it to only add on to the other styles?

Using add_style style index on add_row gives error

As mentioned in #14 (comment)

For no implicit conversion of Integer into Hash this is another error I was wondering how didnt get triggered. Seemed you failed to mention this. I can make a separate PR to resolve this likely.

# Not working
border = s.add_style border: { style: :thin, color: "000000" }
sheet.add_row ['1', '2', '3', '4'], style: border
no implicit conversion of Integer into Hash

Seems we need to modify the worksheet#add_styles method to handle passing of style index (style number / style object)

is it possible to style or add border to empty cell?

or the only way is to hack the cell with '' ?

I build my spreadsheet with empty row and nil row ( is that good practices?)

  sheet.add_row ['Consignee', nil, ": #{@job.company.name}", nil, nil, nil, "Vessel", ": #{@job.vessel_name}"], offset: 1
  sheet.add_row
  sheet.add_row ["DESCRIPTION", nil, nil, nil, "QTY", "UNIT", "CHARGE", "NET VALUE"], offset: 1
  14.times do
    sheet.add_row
  end
  sheet.add_row ["Payment Term : COD", nil, nil, nil, nil, nil, "SUB TOTAL", "JPY"], offset: 1

whenever I try to add style or border I got this
undefined method `row' for nil:NilClass

relevant issues:
#26
#27
randym/axlsx#586

Can not add border style for row

I try to add style border for row but I away get the error: undefined method `row' for nil:NilClass
screen shot 2018-08-03 at 14 56 17

This is my xlsx file when not add style.
screen shot 2018-08-03 at 15 00 52

please tech me where I wrong, or can I must config somewhere ?
Thanks :)

Improve test suite automation

It would be a huge improvement to the test suite if the tests validated the xml contents of the spreadsheets automatically instead of requiring a manual look at the test spreadsheets.

I would love any PR's or contributions that could help improve our tests. Some test examples to get started could be found within the axlsx repo.

Error when using dxf style with other styles

I get an error with the following reproduction:

require 'bundler/inline'

gemfile do
  source 'https://rubygems.org'

  gem 'caxlsx', "= 3.0.1"
  gem 'axlsx_styler', "= 1.0.0"
end

# Monkey-patch a "fix" by uncommenting the line below and commenting the line
# that follows it
module AxlsxStyler
  module Styles
    def add_style(*args)
      style = args.first

      self.style_index ||= {}

      raw_style = {type: :xf, name: 'Arial', sz: 11, family: 1}.merge(style)
      if raw_style[:format_code]
        raw_style.delete(:num_fmt)
      end

      index = style_index.key(raw_style)
      if !index
        index = super
        # self.style_index[index] = raw_style unless raw_style[:type] == :dxf
        self.style_index[index] = raw_style
      end
      return index
    end
  end
end

Axlsx::Package.new do |p|
  %w[first second].each do |sheet_name|
    p.workbook.add_worksheet(name: sheet_name) do |sheet|
      sheet.add_row (1..2).to_a

      sheet.add_style "A1:A1", { bg_color: "AA0000" }
      sheet.add_style "B1:B1", { bg_color: "CC0000" }

      sheet.add_row (1..2).to_a

      highlight = p.workbook.styles.add_style(bg_color: "0000FF", type: :dxf)

      sheet.add_conditional_formatting(
        "A2:B2",
        {
          type: :cellIs,
          operator: :greaterThan,
          formula: "1",
          dxfId: highlight,
          priority: 1
        }
      )

      sheet.add_row (1..2).to_a

      sheet.add_style "A3:B3", { bg_color: "00FF00" }
    end
  end

  p.serialize('simple.xlsx')
end

Running this file gives:

Traceback (most recent call last):
	9: from bug.rb:33:in `<main>'
	8: from bug.rb:33:in `new'
	7: from /Users/owen/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/caxlsx-3.0.1/lib/axlsx/package.rb:29:in `initialize'
	6: from bug.rb:62:in `block in <main>'
	5: from /Users/owen/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/axlsx_styler-1.0.0/lib/axlsx_styler/axlsx_package.rb:5:in `serialize'
	4: from /Users/owen/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/axlsx_styler-1.0.0/lib/axlsx_styler/axlsx_workbook.rb:21:in `apply_styles'
	3: from /Users/owen/.rbenv/versions/2.6.6/lib/ruby/2.6.0/set.rb:338:in `each'
	2: from /Users/owen/.rbenv/versions/2.6.6/lib/ruby/2.6.0/set.rb:338:in `each_key'
	1: from /Users/owen/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/axlsx_styler-1.0.0/lib/axlsx_styler/axlsx_workbook.rb:29:in `block in apply_styles'
/Users/owen/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/caxlsx-3.0.1/lib/axlsx/workbook/worksheet/cell.rb:296:in `style=': Invalid cellXfs id (ArgumentError)

I tracked a "fix" down by adding the commented line in the code, I'm not quite sure I follow what's going on, but hopefully this is helpful

ActiveSupport lock

With the latest v0.1.6 version, ActiveSupport is now locked to the 3.x family versions, which is a problem for people using a any library depending from greater versions of ActiveSupport.

For instance any version of rails >= 4.x:

Bundler could not find compatible versions for gem "activesupport":
  In snapshot (Gemfile.lock):
    activesupport (= 5.0.0.1)

  In Gemfile:
    activemodel-serializers-xml (~> 1.0.0) was resolved to 1.0.0, which depends on
      activesupport (> 5.x)

    rails (~> 5.0.0) was resolved to 5.0.0.1, which depends on
      activejob (= 5.0.0.1) was resolved to 5.0.0.1, which depends on
        globalid (>= 0.3.6) was resolved to 0.3.7, which depends on
          activesupport (>= 4.1.0)

    axlsx_styler (~> 0.1.6) was resolved to 0.1.6, which depends on
      activesupport (~> 3.1)

Add all available style options section to readme

I think it would be fantastic to have a section in the readme which we can use as reference for all available style options.

For example I just had to look up all of the available border styles in the axlsx documentation which by the way are :none :thin :medium :dashed :dotted :thick :double :hair :mediumDashed :dashDot :mediumDashDot :dashDotDot :mediumDashDotDot :slantDashDot

Another example is format instructions for number_format_code.

I would be interested in helping compile this list. As an added bonus this would probably drive a lot of axlsx traffic to this useful gem. What do you think about adding this.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.