使用AXLSX gem将多个样式应用于Excel电子表格中的单元格

时间:2014-11-14 15:18:47

标签: ruby excel axlsx

我正在使用AXLSX Ruby gem来生成Excel报告,我在以模块化方式将几种样式应用于单元格时遇到了问题。

这是一个只有两种样式的例子(“在背景上”和“在背景上加粗”),

require 'axlsx'

axlsx = Axlsx::Package.new
workbook = axlsx.workbook

with_background = workbook.styles.add_style bg_color: "E2D3EB"
bold_with_background = workbook.styles.add_style bg_color: "E2D3EB", b: true

workbook.add_worksheet do |sheet|
  sheet.add_row
  sheet.add_row ["", "Product", "Category", "Price"], style: [0, bold_with_background, bold_with_background, bold_with_background]
  sheet.add_row ["", "Butter", "Dairy", 4.99], style: [0, with_background, with_background, with_background]
  sheet.add_row ["", "Bread", "Baked Goods", 3.45], style: [0, with_background, with_background, with_background]
  sheet.add_row ["", "Broccoli", "Produce", 2.99], style: [0, with_background, with_background, with_background]
end

axlsx.serialize "grocery.xlsx"

这是结果,

enter image description here

现在,假设我必须在此表周围应用边框。如果我理解正确的话,我必须有很多样式才能达到目的:“在左上角的背景上加粗”,“在上边缘的背景上加粗”,“在右上角的背景上加粗”,“在右边缘的背景上“等等。

有没有办法将几种样式应用于单元格,而不必为每种可能的基本样式组合声明样式?

我想要像

这样的东西
sheet["B2"].add_style(bold).add_style(background).add_style(top_left_edge)

但不确定gem是否实现了类似的解决方案。

有什么想法吗?谢谢!

2 个答案:

答案 0 :(得分:3)

仅供参考,有一种方法可以使用“差异样式”来实现。 Look at the docs on styles.rb

基本上,您声明您的样式类型为:dxf。默认值为:xf。其他一切都是一样的。从上面的链接(标题,货币和百分比是前面定义的正常样式):

p = Axlsx::Package.new
wb = p.workbook
ws = wb.add_worksheet

# define your styles
profitable = wb.styles.add_style(:bg_color => "FFFF0000",
                           :fg_color=>"#FF000000",
                           :type => :dxf)

ws.add_row ["Genreated At:", Time.now], :styles=>[nil, date_time]
ws.add_row ["Previous Year Quarterly Profits (JPY)"], :style=>title
ws.add_row ["Quarter", "Profit", "% of Total"], :style=>title
ws.add_row ["Q1", 4000, 40], :style=>[title, currency, percent]
ws.add_row ["Q2", 3000, 30], :style=>[title, currency, percent]
ws.add_row ["Q3", 1000, 10], :style=>[title, currency, percent]
ws.add_row ["Q4", 2000, 20], :style=>[title, currency, percent]

ws.add_conditional_formatting("A1:A7", { :type => :cellIs, :operator => :greaterThan, :formula => "2000", :dxfId => profitable, :priority => 1 })
f = File.open('example_differential_styling', 'w')
p.serialize(f)

答案 1 :(得分:2)

我设法通过猴子修补Axlsx类来覆盖单元格样式。我们的想法是首先以Ruby哈希的形式将原始样式应用于单元格。完成后,可以为工作簿生成Axlsx个样式并应用它们。我现在可以将标记与样式分开,将样式应用为

sheet["B2:D2"].add_style(b: true)
sheet["B2:D5"].add_style(bg_color: "E2D3EB")
workbook.apply_styles

以下是我的hacky解决方案的完整列表。这并不包括识别应该在专业代码中完成的其他事情的独特风格。期待任何反馈。

require 'axlsx'

class Array
  def add_style(style)
    return unless map{ |e| e.kind_of? Axlsx::Cell }.uniq.first
    each { |cell| cell.add_style(style) }
  end
end

class Axlsx::Workbook
  attr_accessor :styled_cells

  def add_styled_cell(cell)
    self.styled_cells ||= []
    self.styled_cells << cell
  end

  def apply_styles
    return unless styled_cells
    styled_cells.each do |cell|
      cell.style = styles.add_style(cell.raw_style)
    end
  end
end

class Axlsx::Cell
  attr_accessor :raw_style

  def workbook
    row.worksheet.workbook
  end

  def add_style(style)
    self.raw_style ||= {}
    self.raw_style = raw_style.merge(style)
    workbook.add_styled_cell(self)
  end
end

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["B2:D2"].add_style(b: true)
  sheet["B2:D5"].add_style(bg_color: "E2D3EB")
end

workbook.apply_styles

axlsx.serialize "grocery.xlsx"

修改:我已经将我的解决方案倾斜并将其解压缩为一个宝石https://github.com/sakovias/axlsx_styler