3

我正在使用AXLSXRuby 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"

这是结果,

在此处输入图像描述

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

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

我想要类似的东西

sheet["B2"].add_style(bold).add_style(background).add_style(top_left_edge)

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

有任何想法吗?谢谢!

4

2 回答 2

3

仅供参考,有一种方法可以使用“不同的样式”来做到这一点。查看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)
于 2014-12-05T16:37:26.903 回答
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"

编辑:我已经优化了我的解决方案并将其提取到一个 gem https://github.com/sakovias/axlsx_styler

于 2014-11-14T20:44:11.513 回答