openxml-xlsx 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +20 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/example +93 -0
- data/lib/xlsx.rb +28 -0
- data/lib/xlsx/elements.rb +8 -0
- data/lib/xlsx/elements/alignment.rb +20 -0
- data/lib/xlsx/elements/border.rb +26 -0
- data/lib/xlsx/elements/border_component.rb +19 -0
- data/lib/xlsx/elements/border_style.rb +20 -0
- data/lib/xlsx/elements/cell.rb +94 -0
- data/lib/xlsx/elements/defined_name.rb +11 -0
- data/lib/xlsx/elements/font.rb +20 -0
- data/lib/xlsx/elements/implied_number_format.rb +5 -0
- data/lib/xlsx/elements/indexed_color.rb +11 -0
- data/lib/xlsx/elements/number_format.rb +45 -0
- data/lib/xlsx/elements/pattern_fill.rb +18 -0
- data/lib/xlsx/elements/relationship.rb +18 -0
- data/lib/xlsx/elements/row.rb +35 -0
- data/lib/xlsx/elements/style.rb +27 -0
- data/lib/xlsx/elements/table_column.rb +6 -0
- data/lib/xlsx/elements/theme_color.rb +11 -0
- data/lib/xlsx/package.rb +50 -0
- data/lib/xlsx/parts.rb +8 -0
- data/lib/xlsx/parts/shared_strings.rb +26 -0
- data/lib/xlsx/parts/stylesheet.rb +78 -0
- data/lib/xlsx/parts/table.rb +34 -0
- data/lib/xlsx/parts/workbook.rb +66 -0
- data/lib/xlsx/parts/worksheet.rb +88 -0
- data/lib/xlsx/version.rb +3 -0
- data/xlsx.gemspec +32 -0
- metadata +191 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a010100989ff2ab9093bfdea05d3535cf8de0eb1
|
4
|
+
data.tar.gz: 55f156afa2e40ad7a5f73b82a6e366dd39972d18
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b6cbe628be8b61481747178a1cc4e6a9bbac64477412f39c34cb5ebbc9785563d910bf172030330e49e6ae01fd14a96717f719b32d58ae0384d2b9062eaf6469
|
7
|
+
data.tar.gz: ca54754a84cf214773b0d4aeb61d0ecd78d2c05e5d6660dc2e6d5059b49e8cd7dcff6e86ad899c94b3fa047174410636bfeaf6bd66ef1951bade31cd3a8c8842
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2013 Bob Lail
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "xlsx"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
data/example
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.push Dir.pwd + "/lib"
|
4
|
+
require "xlsx"
|
5
|
+
package = Xlsx::Package.new
|
6
|
+
workbook = package.workbook
|
7
|
+
worksheet = workbook.worksheets[0]
|
8
|
+
|
9
|
+
include Xlsx::Elements
|
10
|
+
|
11
|
+
workbook.add_defined_names({name: "Alpha", formula:"Sheet1!$A$1"}, {name: "Charlie", formula:"Sheet1!$C$1"})
|
12
|
+
|
13
|
+
worksheet.merge_cells("B1:G1", "A8:G8")
|
14
|
+
|
15
|
+
currency = NumberFormat.new("\"$\"#,##0.00")
|
16
|
+
|
17
|
+
heading = Font.new("Calibri", 25, {bold: true, italic: true, underline: true, color: IndexedColor.new(55)})
|
18
|
+
|
19
|
+
fill2 = PatternFill.new("solid",
|
20
|
+
ThemeColor.new(0, -4.9989318521683403E-2),
|
21
|
+
IndexedColor.new(65))
|
22
|
+
fill3 = PatternFill.new("solid",
|
23
|
+
ThemeColor.new(8, 0.79998168889431442),
|
24
|
+
IndexedColor.new(65))
|
25
|
+
fill4 = PatternFill.new("solid",
|
26
|
+
ThemeColor.new(8, 0.59999389629810485),
|
27
|
+
IndexedColor.new(65))
|
28
|
+
|
29
|
+
left = Alignment.new("left", "center")
|
30
|
+
center = Alignment.new("center", "center")
|
31
|
+
right = Alignment.new("right", "center")
|
32
|
+
|
33
|
+
border1 = Border.new(top: BorderComponent.new(BorderStyle::THICK))
|
34
|
+
border2 = Border.new(
|
35
|
+
left: BorderComponent.new(BorderStyle::HAIR, IndexedColor.new(12)),
|
36
|
+
right: BorderComponent.new(BorderStyle::SLANT_DASH_DOT, IndexedColor.new(45))
|
37
|
+
)
|
38
|
+
border3 = Border.new(bottom: BorderComponent.new(BorderStyle::DOUBLE, IndexedColor.new(13)))
|
39
|
+
|
40
|
+
worksheet.column_widths(
|
41
|
+
1 => 3.83203125,
|
42
|
+
2 => 11.1640625,
|
43
|
+
5 => 36.1640625
|
44
|
+
)
|
45
|
+
|
46
|
+
|
47
|
+
worksheet.add_rows(
|
48
|
+
{ number: 1,
|
49
|
+
cells: [
|
50
|
+
{ column: 2, value: "Test", style: {font: heading, alignment: left} }] },
|
51
|
+
{ number: 2,
|
52
|
+
cells: [
|
53
|
+
{ column: 2, value: "Column 1", style: {fill: fill2, alignment: left, border: border2} },
|
54
|
+
{ column: 3, value: "Column 2", style: {fill: fill2, alignment: center, border: border3} },
|
55
|
+
{ column: 4, value: "Column 3", style: {fill: fill2, alignment: right, border: border1} },
|
56
|
+
{ column: 5, value: "Column 4", style: {fill: fill4, alignment: right} }] },
|
57
|
+
{ number: 3,
|
58
|
+
cells: [
|
59
|
+
{ column: 2, value: 1, style: {alignment: left, border: border2} },
|
60
|
+
{ column: 3, value: Time.new(2014, 6, 20, 8, 30), style: {format: NumberFormat::DATETIME, alignment: center, border: border3} },
|
61
|
+
{ column: 4, value: 65, style: {format: currency, alignment: right, border: border1} },
|
62
|
+
{ column: 5, value: "hi", style: {format: currency, fill: fill3, alignment: right} }] },
|
63
|
+
{ number: 4,
|
64
|
+
hidden: true,
|
65
|
+
cells: [
|
66
|
+
{ column: 2, value: 2, style: {alignment: left, border: border2} },
|
67
|
+
{ column: 3, value: Date.new(2014, 7, 21), style: {format: NumberFormat::DAY_MONTH, alignment: center, border: border3} },
|
68
|
+
{ column: 4, value: 14, style: {format: currency, alignment: right, border: border1} },
|
69
|
+
{ column: 5, value: "hi", style: {format: currency, fill: fill3, alignment: right} }] },
|
70
|
+
{ number: 5,
|
71
|
+
cells: [
|
72
|
+
{ column: 2, value: 3, style: {alignment: left, border: border2} },
|
73
|
+
{ column: 3, value: Date.new(2014, 8, 24), style: {format: NumberFormat::DAY_MONTH, alignment: center, border: border3} },
|
74
|
+
{ column: 4, value: 13, style: {format: currency, alignment: right, border: border1} },
|
75
|
+
{ column: 5, value: "hi", style: {format: currency, fill: fill3, alignment: right} }] },
|
76
|
+
{ number: 6,
|
77
|
+
cells: [
|
78
|
+
{ column: 2, value: 4, style: {alignment: left, border: border2} },
|
79
|
+
{ column: 3, value: Date.new(2014, 8, 24), style: {format: NumberFormat::DAY_MONTH, alignment: center, border: border3} },
|
80
|
+
{ column: 4, value: 9, style: {format: currency, alignment: right, border: border1} },
|
81
|
+
{ column: 5, value: "hi", style: {format: currency, fill: fill3, alignment: right} }] })
|
82
|
+
|
83
|
+
worksheet.add_table 1, "Table1", "B2:E6", [
|
84
|
+
TableColumn.new("Column 1"),
|
85
|
+
TableColumn.new("Column 2"),
|
86
|
+
TableColumn.new("Column 3"),
|
87
|
+
TableColumn.new("Column 4")
|
88
|
+
]
|
89
|
+
|
90
|
+
filename = "gemtest1.xlsx"
|
91
|
+
system "rm ~/Desktop/#{filename}"
|
92
|
+
package.save File.expand_path("~/Desktop/#{filename}")
|
93
|
+
exec "open ~/Desktop/#{filename}"
|
data/lib/xlsx.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
module Xlsx
|
2
|
+
REL_DOCUMENT = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument".freeze
|
3
|
+
REL_WORKSHEET = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet".freeze
|
4
|
+
REL_STYLES = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles".freeze
|
5
|
+
REL_SHARED_STRINGS = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings".freeze
|
6
|
+
REL_CALC_CHAIN = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/calcChain".freeze
|
7
|
+
REL_THEME = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme".freeze
|
8
|
+
REL_TABLE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/table".freeze
|
9
|
+
|
10
|
+
TYPE_WORKBOOK = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml".freeze
|
11
|
+
TYPE_WORKSHEET = "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml".freeze
|
12
|
+
TYPE_THEME = "application/vnd.openxmlformats-officedocument.theme+xml".freeze
|
13
|
+
TYPE_STYLES = "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml".freeze
|
14
|
+
TYPE_SHARED_STRINGS = "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml".freeze
|
15
|
+
TYPE_CALC_CHAIN = "application/vnd.openxmlformats-officedocument.spreadsheetml.calcChain+xml".freeze
|
16
|
+
TYPE_CORE_PROPS = "application/vnd.openxmlformats-package.core-properties+xml".freeze
|
17
|
+
TYPE_APP_PROPS = "application/vnd.openxmlformats-officedocument.extended-properties+xml".freeze
|
18
|
+
TYPE_TABLE = "application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml".freeze
|
19
|
+
|
20
|
+
def self.index!(collection, item)
|
21
|
+
collection.index(item) || collection.push(item).length - 1
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
require "xlsx/elements"
|
27
|
+
require "xlsx/package"
|
28
|
+
require "xlsx/parts"
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Xlsx
|
2
|
+
module Elements
|
3
|
+
class Alignment < Struct.new(:horizontal, :vertical, :indent, :wrapText)
|
4
|
+
|
5
|
+
def attributes
|
6
|
+
{}.tap do |attrs|
|
7
|
+
attrs[:horizontal] = horizontal if horizontal
|
8
|
+
attrs[:vertical] = vertical if vertical
|
9
|
+
attrs[:indent] = indent if indent
|
10
|
+
attrs[:wrapText] = wrapText if wrapText
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_xml(xml)
|
15
|
+
xml.alignment(attributes)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Xlsx
|
2
|
+
module Elements
|
3
|
+
class Border
|
4
|
+
attr_reader :left_component, :right_component, :top_component, :bottom_component, :diagonal_component
|
5
|
+
|
6
|
+
def initialize(options={})
|
7
|
+
@left_component = options.fetch(:left, BorderComponent.new)
|
8
|
+
@right_component = options.fetch(:right, BorderComponent.new)
|
9
|
+
@top_component = options.fetch(:top, BorderComponent.new)
|
10
|
+
@bottom_component = options.fetch(:bottom, BorderComponent.new)
|
11
|
+
@diagonal_component = options.fetch(:diagonal, BorderComponent.new)
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_xml(xml)
|
15
|
+
xml.border do
|
16
|
+
left_component.to_xml("left", xml)
|
17
|
+
right_component.to_xml("right", xml)
|
18
|
+
top_component.to_xml("top", xml)
|
19
|
+
bottom_component.to_xml("bottom", xml)
|
20
|
+
diagonal_component.to_xml("diagonal", xml)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Xlsx
|
2
|
+
module Elements
|
3
|
+
class BorderComponent < Struct.new(:style, :color)
|
4
|
+
|
5
|
+
def to_xml(name, xml)
|
6
|
+
if style && color
|
7
|
+
xml.public_send(name, style: style) do
|
8
|
+
color.to_xml("color", xml)
|
9
|
+
end
|
10
|
+
elsif style
|
11
|
+
xml.public_send(name, style: style)
|
12
|
+
else
|
13
|
+
xml.public_send(name)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Xlsx
|
2
|
+
module Elements
|
3
|
+
class BorderStyle
|
4
|
+
NONE = "none".freeze
|
5
|
+
THIN = "thin".freeze
|
6
|
+
MEDIUM = "medium".freeze
|
7
|
+
DASHED = "dashed".freeze
|
8
|
+
DOTTED = "dotted".freeze
|
9
|
+
THICK = "thick".freeze
|
10
|
+
DOUBLE = "double".freeze
|
11
|
+
HAIR = "hair".freeze
|
12
|
+
MEDIUM_DASHED = "mediumDashed".freeze
|
13
|
+
DASH_DOT = "dashDot".freeze
|
14
|
+
MEDIUM_DASH_DOT = "mediumDashDot".freeze
|
15
|
+
DASH_DOT_DOT = "dashDotDot".freeze
|
16
|
+
MEDIUM_DASH_DOT_DOT = "mediumDashDotDot".freeze
|
17
|
+
SLANT_DASH_DOT = "slantDashDot".freeze
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require "date"
|
2
|
+
|
3
|
+
module Xlsx
|
4
|
+
module Elements
|
5
|
+
class Cell
|
6
|
+
attr_reader :row, :column, :value, :type, :style, :formula
|
7
|
+
|
8
|
+
def initialize(row, options={})
|
9
|
+
@row = row
|
10
|
+
@column = options.fetch(:column)
|
11
|
+
@value = options[:value]
|
12
|
+
case value
|
13
|
+
when String
|
14
|
+
@type = :string
|
15
|
+
@string_id = package.string_ref(value)
|
16
|
+
when Date then
|
17
|
+
@type = :date
|
18
|
+
@serial_date = to_serial_date(value)
|
19
|
+
when Time then
|
20
|
+
@type = :time
|
21
|
+
@serial_time = to_serial_time(value)
|
22
|
+
else
|
23
|
+
@type = :general
|
24
|
+
end
|
25
|
+
@style = package.style_ref(options[:style]) if options.key? :style
|
26
|
+
@formula = options[:formula]
|
27
|
+
end
|
28
|
+
|
29
|
+
def id
|
30
|
+
"#{column_letter}#{row.number}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def column_letter
|
34
|
+
bytes = []
|
35
|
+
remaining = column
|
36
|
+
while remaining > 0
|
37
|
+
bytes.unshift (remaining - 1) % 26 + 65
|
38
|
+
remaining = (remaining - 1) / 26
|
39
|
+
end
|
40
|
+
bytes.pack "c*"
|
41
|
+
end
|
42
|
+
|
43
|
+
def worksheet
|
44
|
+
row.worksheet
|
45
|
+
end
|
46
|
+
|
47
|
+
def workbook
|
48
|
+
worksheet.workbook
|
49
|
+
end
|
50
|
+
|
51
|
+
def package
|
52
|
+
workbook.package
|
53
|
+
end
|
54
|
+
|
55
|
+
def to_xml(xml)
|
56
|
+
attributes = {"r" => id}
|
57
|
+
attributes.merge!("s" => style) if style
|
58
|
+
attributes.merge!("t" => "s") if type == :string
|
59
|
+
|
60
|
+
value = self.value
|
61
|
+
value = string_id if type == :string
|
62
|
+
value = serial_date if type == :date
|
63
|
+
value = serial_time if type == :time
|
64
|
+
|
65
|
+
xml.c(attributes) do
|
66
|
+
xml.f formula if formula
|
67
|
+
xml.v value if value
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
attr_reader :string_id, :serial_date, :serial_time
|
73
|
+
|
74
|
+
EXCEL_ANCHOR_DATE = Date.new(1900, 1, 1).freeze
|
75
|
+
SECONDS_PER_DAY = 86400.freeze
|
76
|
+
|
77
|
+
def to_serial_date(date)
|
78
|
+
# Excel stores dates as the number of days since 1900-Jan-0
|
79
|
+
# Excel behaves as if 1900 was a leap year, so the number is
|
80
|
+
# generally 1 greater than you would expect.
|
81
|
+
# http://www.cpearson.com/excel/datetime.htm
|
82
|
+
(date - EXCEL_ANCHOR_DATE).to_i + 2
|
83
|
+
end
|
84
|
+
|
85
|
+
def to_serial_time(time)
|
86
|
+
date = to_serial_date(time.to_date)
|
87
|
+
|
88
|
+
seconds_since_midnight = time.hour * 3600 + time.min * 60 + time.sec
|
89
|
+
date + (seconds_since_midnight.to_f / SECONDS_PER_DAY)
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Xlsx
|
2
|
+
module Elements
|
3
|
+
class Font < Struct.new(:name, :size, :styles)
|
4
|
+
|
5
|
+
def to_xml(xml)
|
6
|
+
xml.font do
|
7
|
+
xml.sz val: size
|
8
|
+
xml.name val: name
|
9
|
+
if styles
|
10
|
+
xml.b if styles[:bold]
|
11
|
+
xml.i if styles[:italic]
|
12
|
+
xml.u if styles[:underline]
|
13
|
+
styles[:color].to_xml("color", xml) if styles[:color]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require "xlsx/elements/implied_number_format"
|
2
|
+
|
3
|
+
module Xlsx
|
4
|
+
module Elements
|
5
|
+
class NumberFormat < Struct.new(:format)
|
6
|
+
INTEGER = ImpliedNumberFormat.new(1).freeze # 0
|
7
|
+
DECIMAL = ImpliedNumberFormat.new(2).freeze # 0.00
|
8
|
+
INTEGER_THOUSANDS = ImpliedNumberFormat.new(3).freeze # #,##0
|
9
|
+
DECIMAL_THOUSANDS = ImpliedNumberFormat.new(4).freeze # #,##0.00
|
10
|
+
|
11
|
+
INTEGER_PERCENT = ImpliedNumberFormat.new(9).freeze # 0%
|
12
|
+
DECIMAL_PERCENT = ImpliedNumberFormat.new(10).freeze # 0.00%
|
13
|
+
SCIENTIFIC = ImpliedNumberFormat.new(11).freeze # 0.00E+00
|
14
|
+
FRACTION = ImpliedNumberFormat.new(12).freeze # ?/?
|
15
|
+
FRACTION2 = ImpliedNumberFormat.new(13).freeze # ??/??
|
16
|
+
DATE = ImpliedNumberFormat.new(14).freeze # mm-dd-yy
|
17
|
+
DATE_ALT = ImpliedNumberFormat.new(15).freeze # d-mmm-yy
|
18
|
+
DAY_MONTH = ImpliedNumberFormat.new(16).freeze # d-mmm
|
19
|
+
MONTH_YEAR = ImpliedNumberFormat.new(17).freeze # mmm-yy
|
20
|
+
TIME = ImpliedNumberFormat.new(18).freeze # h:mm AM/PM
|
21
|
+
TIME_SECONDS = ImpliedNumberFormat.new(19).freeze # h:mm:ss AM/PM
|
22
|
+
TIME_ALT = ImpliedNumberFormat.new(20).freeze # h:mm
|
23
|
+
TIME_SECONDS_ALT = ImpliedNumberFormat.new(21).freeze # h:mm:ss
|
24
|
+
DATETIME = ImpliedNumberFormat.new(22).freeze # m/d/yy h:mm
|
25
|
+
|
26
|
+
FINANCIAL_INTEGER = ImpliedNumberFormat.new(37).freeze # #,##0 ;(#,##0)
|
27
|
+
FINANCIAL_INTEGER_RED = ImpliedNumberFormat.new(38).freeze # #,##0 ;[Red](#,##0)
|
28
|
+
FINANCIAL_DECIMAL = ImpliedNumberFormat.new(39).freeze # #,##0.00 ;(#,##0.00)
|
29
|
+
FINANCIAL_DECIMAL_RED = ImpliedNumberFormat.new(40).freeze # #,##0.00 ;[Red](#,##0.00)
|
30
|
+
|
31
|
+
INTERVAL = ImpliedNumberFormat.new(45).freeze # mm:ss
|
32
|
+
INTERVAL_HOURS = ImpliedNumberFormat.new(46).freeze # [h]:mm:ss
|
33
|
+
TIMESTAMP = ImpliedNumberFormat.new(47).freeze # mmss.0
|
34
|
+
# SCIENTIFIC_ALT = ImpliedNumberFormat.new(48).freeze # ##0.0E+0
|
35
|
+
# UNKONWN = ImpliedNumberFormat.new(49).freeze # @
|
36
|
+
|
37
|
+
|
38
|
+
|
39
|
+
def to_xml(id, xml)
|
40
|
+
xml.numFmt(numFmtId: id, formatCode: format)
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Xlsx
|
2
|
+
module Elements
|
3
|
+
class PatternFill < Struct.new(:type, :foreground_color, :background_color)
|
4
|
+
|
5
|
+
def to_xml(xml)
|
6
|
+
xml.fill do
|
7
|
+
xml.patternFill(patternType: type) do
|
8
|
+
if type.to_s == "solid"
|
9
|
+
foreground_color.to_xml("fgColor", xml)
|
10
|
+
background_color.to_xml("bgColor", xml)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require "securerandom"
|
2
|
+
|
3
|
+
module Xlsx
|
4
|
+
module Elements
|
5
|
+
class Relationship < Struct.new(:type, :target, :id)
|
6
|
+
|
7
|
+
def initialize(type, target, id=nil)
|
8
|
+
id ||= "R#{SecureRandom.hex}"
|
9
|
+
super type, target, id
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_xml(xml)
|
13
|
+
xml.Relationship("Id" => id, "Type" => type, "Target" => target)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Xlsx
|
2
|
+
module Elements
|
3
|
+
class Row
|
4
|
+
attr_reader :worksheet, :number, :height, :hidden, :cells
|
5
|
+
|
6
|
+
def initialize(worksheet, options={})
|
7
|
+
@worksheet = worksheet
|
8
|
+
@number = options.fetch(:number)
|
9
|
+
@height = options[:height]
|
10
|
+
@hidden = options[:hidden]
|
11
|
+
@cells = []
|
12
|
+
|
13
|
+
Array(options[:cells]).each do |attributes|
|
14
|
+
add_cell attributes
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def add_cell(attributes)
|
19
|
+
cells.push Xlsx::Elements::Cell.new(self, attributes)
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_xml(xml)
|
23
|
+
attributes = {"r" => number}
|
24
|
+
attributes.merge!("ht" => height, "customHeight" => 1) if height
|
25
|
+
attributes.merge!("hidden" => 1) if hidden
|
26
|
+
xml.row(attributes) do
|
27
|
+
cells.each do |cell|
|
28
|
+
cell.to_xml(xml)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Xlsx
|
2
|
+
module Elements
|
3
|
+
class Style < Struct.new(:format_id, :font_id, :fill_id, :border_id, :alignment)
|
4
|
+
|
5
|
+
def initialize(format_id=0, font_id=0, fill_id=0, border_id=0, alignment=nil)
|
6
|
+
super format_id || 0, font_id || 0, fill_id || 0, border_id || 0, alignment
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_xml(xml)
|
10
|
+
attributes = {
|
11
|
+
numFmtId: format_id,
|
12
|
+
fontId: font_id,
|
13
|
+
fillId: fill_id,
|
14
|
+
borderId: border_id }
|
15
|
+
attributes.merge!(applyNumberFormat: 1) if format_id > 0
|
16
|
+
attributes.merge!(applyFont: 1) if font_id > 0
|
17
|
+
attributes.merge!(applyFill: 1) if fill_id > 0
|
18
|
+
attributes.merge!(applyBorder: 1) if border_id > 0
|
19
|
+
attributes.merge!(applyAlignment: 1) if alignment
|
20
|
+
xml.xf(attributes) do
|
21
|
+
alignment.to_xml(xml) if alignment
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/xlsx/package.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require "open_xml/package"
|
2
|
+
|
3
|
+
module Xlsx
|
4
|
+
class Package < OpenXml::Package
|
5
|
+
attr_reader :xl_rels,
|
6
|
+
:shared_strings,
|
7
|
+
:stylesheet,
|
8
|
+
:workbook
|
9
|
+
|
10
|
+
|
11
|
+
content_types do
|
12
|
+
override "/xl/workbook.xml", TYPE_WORKBOOK
|
13
|
+
override "/xl/worksheets/sheet1.xml", TYPE_WORKSHEET
|
14
|
+
override "/xl/sharedStrings.xml", TYPE_SHARED_STRINGS
|
15
|
+
override "/xl/styles.xml", TYPE_STYLES
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
def initialize
|
20
|
+
super
|
21
|
+
rels.add_relationship REL_DOCUMENT, "xl/workbook.xml"
|
22
|
+
|
23
|
+
@xl_rels = OpenXml::Parts::Rels.new([
|
24
|
+
{ "Type" => REL_SHARED_STRINGS, "Target" => "sharedStrings.xml" },
|
25
|
+
{ "Type" => REL_STYLES, "Target" => "styles.xml" }
|
26
|
+
])
|
27
|
+
@shared_strings = Xlsx::Parts::SharedStrings.new
|
28
|
+
@stylesheet = Xlsx::Parts::Stylesheet.new
|
29
|
+
@workbook = Xlsx::Parts::Workbook.new(self)
|
30
|
+
|
31
|
+
# docProps/app.xml
|
32
|
+
# docProps/core.xml
|
33
|
+
add_part "xl/_rels/workbook.xml.rels", xl_rels
|
34
|
+
# xl/calcChain.xml
|
35
|
+
add_part "xl/sharedStrings.xml", shared_strings
|
36
|
+
add_part "xl/styles.xml", stylesheet
|
37
|
+
# xl/theme/theme1.xml
|
38
|
+
add_part "xl/workbook.xml", workbook
|
39
|
+
end
|
40
|
+
|
41
|
+
def string_ref(string)
|
42
|
+
shared_strings.reference_of(string)
|
43
|
+
end
|
44
|
+
|
45
|
+
def style_ref(style)
|
46
|
+
stylesheet.reference_of(style)
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
data/lib/xlsx/parts.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
module Xlsx
|
2
|
+
module Parts
|
3
|
+
class SharedStrings < OpenXml::Part
|
4
|
+
attr_reader :strings
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@strings = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def reference_of(string)
|
11
|
+
Xlsx.index!(strings, string)
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_xml
|
15
|
+
build_standalone_xml do |xml|
|
16
|
+
xml.sst(xmlns: "http://schemas.openxmlformats.org/spreadsheetml/2006/main", uniqueCount: strings.length) do
|
17
|
+
strings.each do |string|
|
18
|
+
xml.si { xml.t(string) }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module Xlsx
|
2
|
+
module Parts
|
3
|
+
class Stylesheet < OpenXml::Part
|
4
|
+
include Xlsx::Elements
|
5
|
+
|
6
|
+
attr_reader :formats, :fonts, :fills, :borders, :styles
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@formats = []
|
10
|
+
@fonts = [Font.new("Calibri", 12)]
|
11
|
+
@fills = [PatternFill.new("none"), PatternFill.new("gray125")]
|
12
|
+
@borders = [Border.new]
|
13
|
+
@styles = [Style.new]
|
14
|
+
end
|
15
|
+
|
16
|
+
def reference_of(options={})
|
17
|
+
case format = options[:format]
|
18
|
+
when NumberFormat
|
19
|
+
options[:format_id] = Xlsx.index!(formats, format) + NUMBER_FORMAT_START_ID
|
20
|
+
when ImpliedNumberFormat
|
21
|
+
options[:format_id] = format.id
|
22
|
+
end
|
23
|
+
options[:font_id] = Xlsx.index!(fonts, options[:font]) if options.key? :font
|
24
|
+
options[:fill_id] = Xlsx.index!(fills, options[:fill]) if options.key? :fill
|
25
|
+
options[:border_id] = Xlsx.index!(borders, options[:border]) if options.key? :border
|
26
|
+
|
27
|
+
style = Style.new(
|
28
|
+
options.fetch(:format_id, 0),
|
29
|
+
options.fetch(:font_id, 0),
|
30
|
+
options.fetch(:fill_id, 0),
|
31
|
+
options.fetch(:border_id, 0),
|
32
|
+
options.fetch(:alignment, nil))
|
33
|
+
|
34
|
+
Xlsx.index!(styles, style)
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_xml
|
38
|
+
build_standalone_xml do |xml|
|
39
|
+
xml.styleSheet(xmlns: "http://schemas.openxmlformats.org/spreadsheetml/2006/main", "xmlns:mc" => "http://schemas.openxmlformats.org/markup-compatibility/2006") do
|
40
|
+
xml.numFmts(count: formats.length) do
|
41
|
+
formats.each_with_index do |format, index|
|
42
|
+
format.to_xml(index + NUMBER_FORMAT_START_ID, xml)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
xml.fonts(count: fonts.length) do
|
47
|
+
fonts.each do |font|
|
48
|
+
font.to_xml(xml)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
xml.fills(count: fills.length) do
|
53
|
+
fills.each do |fill|
|
54
|
+
fill.to_xml(xml)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
xml.borders(count: borders.length) do
|
59
|
+
borders.each do |border|
|
60
|
+
border.to_xml(xml)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
xml.cellXfs(count: styles.length) do
|
65
|
+
styles.each do |style|
|
66
|
+
style.to_xml(xml)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
NUMBER_FORMAT_START_ID = 165.freeze
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Xlsx
|
2
|
+
module Parts
|
3
|
+
class Table < OpenXml::Part
|
4
|
+
attr_reader :id, :name, :ref, :columns
|
5
|
+
|
6
|
+
def initialize(id, name, ref, columns)
|
7
|
+
@id = id
|
8
|
+
@name = name
|
9
|
+
@ref = ref
|
10
|
+
@columns = columns
|
11
|
+
end
|
12
|
+
|
13
|
+
def filename
|
14
|
+
"table#{id}.xml"
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_xml
|
18
|
+
build_standalone_xml do |xml|
|
19
|
+
xml.table(xmlns: "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
|
20
|
+
id: id, name: name, displayName: name, ref: ref, totalsRowShown: 0) do
|
21
|
+
xml.autoFilter ref: ref
|
22
|
+
xml.tableColumns(count: columns.length) do
|
23
|
+
columns.each_with_index do |column, index|
|
24
|
+
xml.tableColumn(id: index + 1, name: column.name)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
xml.tableStyleInfo(name: "TableStyleLight6", showFirstColumn: 0, showLastColumn: 0, showRowStripes: 1, showColumnStripes: 0)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Xlsx
|
2
|
+
module Parts
|
3
|
+
class Workbook < OpenXml::Part
|
4
|
+
attr_reader :package, :worksheets, :tables, :defined_names
|
5
|
+
|
6
|
+
def initialize(package)
|
7
|
+
@package = package
|
8
|
+
@worksheets = []
|
9
|
+
@tables = []
|
10
|
+
@defined_names =[]
|
11
|
+
add_worksheet
|
12
|
+
end
|
13
|
+
|
14
|
+
def add_worksheet
|
15
|
+
worksheet = Worksheet.new(self, worksheets.length + 1)
|
16
|
+
package.xl_rels.add_relationship(
|
17
|
+
REL_WORKSHEET,
|
18
|
+
"worksheets/sheet#{worksheet.index}.xml",
|
19
|
+
"rId#{worksheet.index}")
|
20
|
+
package.add_part "xl/worksheets/_rels/sheet#{worksheet.index}.xml.rels", worksheet.rels
|
21
|
+
package.add_part "xl/worksheets/sheet#{worksheet.index}.xml", worksheet
|
22
|
+
worksheets.push worksheet
|
23
|
+
end
|
24
|
+
|
25
|
+
def add_table(table)
|
26
|
+
package.content_types.add_override "/xl/tables/#{table.filename}", TYPE_TABLE
|
27
|
+
package.add_part "xl/tables/#{table.filename}", table
|
28
|
+
tables.push table
|
29
|
+
end
|
30
|
+
|
31
|
+
def add_defined_names(*defined_names)
|
32
|
+
defined_names.flatten.each do |attributes|
|
33
|
+
add_defined_name attributes
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def add_defined_name(attributes)
|
38
|
+
defined_names.push Xlsx::Elements::DefinedName.new(attributes[:name], attributes[:formula])
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_xml
|
42
|
+
build_standalone_xml do |xml|
|
43
|
+
xml.workbook(root_namespaces) {
|
44
|
+
xml.sheets { worksheets.each { |worksheet|
|
45
|
+
xml.sheet(
|
46
|
+
"name" => worksheet.name,
|
47
|
+
"sheetId" => worksheet.index,
|
48
|
+
"r:id" => "rId#{worksheet.index}")
|
49
|
+
} }
|
50
|
+
xml.definedNames do
|
51
|
+
defined_names.each { |defined_name| defined_name.to_xml(xml) }
|
52
|
+
end if defined_names.any?
|
53
|
+
}
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def root_namespaces
|
60
|
+
{ "xmlns" => "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
|
61
|
+
"xmlns:r" => 'http://schemas.openxmlformats.org/officeDocument/2006/relationships' }
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module Xlsx
|
2
|
+
module Parts
|
3
|
+
class Worksheet < OpenXml::Part
|
4
|
+
attr_reader :workbook, :index, :rows, :tables, :rels, :cell_ranges
|
5
|
+
|
6
|
+
def initialize(workbook, index)
|
7
|
+
@workbook = workbook
|
8
|
+
@index = index
|
9
|
+
@rows = []
|
10
|
+
@tables = []
|
11
|
+
@cell_ranges = []
|
12
|
+
@rels = OpenXml::Parts::Rels.new
|
13
|
+
@column_widths = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def column_widths(*args)
|
17
|
+
return @column_widths if args.none?
|
18
|
+
@column_widths = args.first
|
19
|
+
end
|
20
|
+
|
21
|
+
def add_rows(*rows)
|
22
|
+
rows.flatten.each do |attributes|
|
23
|
+
add_row attributes
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_row(attributes)
|
28
|
+
rows.push Xlsx::Elements::Row.new(self, attributes)
|
29
|
+
end
|
30
|
+
|
31
|
+
def merge_cells(*ranges)
|
32
|
+
ranges.each { |range| cell_ranges.push range }
|
33
|
+
end
|
34
|
+
|
35
|
+
def add_table(id, name, ref, columns)
|
36
|
+
table = Xlsx::Parts::Table.new(id, name, ref, columns)
|
37
|
+
rels.add_relationship(REL_TABLE, "../tables/#{table.filename}")
|
38
|
+
workbook.add_table table
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_xml
|
42
|
+
build_standalone_xml do |xml|
|
43
|
+
xml.worksheet(root_namespaces) do
|
44
|
+
xml.sheetViews do
|
45
|
+
xml.sheetView(showGridLines: 0, tabSelected: 1, workbookViewId: 0)
|
46
|
+
end
|
47
|
+
xml.sheetFormatPr(baseColWidth: 10, defaultColWidth: 13.33203125, defaultRowHeight: 20, customHeight: 1)
|
48
|
+
xml.cols do
|
49
|
+
column_widths.each do |column, width|
|
50
|
+
xml.col(min: column, max: column, width: width, customWidth: 1)
|
51
|
+
end
|
52
|
+
end if column_widths.any?
|
53
|
+
xml.sheetData do
|
54
|
+
rows.each { |row| row.to_xml(xml) }
|
55
|
+
end
|
56
|
+
xml.mergeCells(count: merge_cells.size) do
|
57
|
+
cell_ranges.each { |range| xml.mergeCell ref: range }
|
58
|
+
end if cell_ranges.any?
|
59
|
+
xml.pageMargins(left: 0.75, right: 0.75, top: 1, bottom: 1, header: 0.5, footer: 0.5)
|
60
|
+
xml.pageSetup(orientation: "portrait", horizontalDpi: 4294967292, verticalDpi: 4294967292)
|
61
|
+
xml.tableParts(count: tables.count) do
|
62
|
+
tables.each do |rel|
|
63
|
+
xml.tablePart("r:id" => rel.id)
|
64
|
+
end
|
65
|
+
end if tables.any?
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def name
|
71
|
+
"Sheet#{index}"
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def root_namespaces
|
77
|
+
{ "xmlns" => "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
|
78
|
+
"xmlns:r" => "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
|
79
|
+
"xmlns:mc" => "http://schemas.openxmlformats.org/markup-compatibility/2006" }
|
80
|
+
end
|
81
|
+
|
82
|
+
def tables
|
83
|
+
rels.select { |rel| rel.type == REL_TABLE }
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
data/lib/xlsx/version.rb
ADDED
data/xlsx.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "xlsx/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "openxml-xlsx"
|
8
|
+
spec.version = Xlsx::VERSION
|
9
|
+
spec.authors = ["Bob Lail"]
|
10
|
+
spec.email = ["bob.lail@cph.org"]
|
11
|
+
|
12
|
+
spec.description = %q{Create Microsoft Excel (.xlsx) files.}
|
13
|
+
spec.summary = %q{Using a simple API, create xlsx files programmatically}
|
14
|
+
spec.license = "MIT"
|
15
|
+
spec.homepage = "https://github.com/concordia-publishing-house/xlsx"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
spec.bindir = "exe"
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.required_ruby_version = "~> 2.0"
|
23
|
+
spec.add_dependency "nokogiri"
|
24
|
+
spec.add_dependency "open_xml_package", "0.1.0"
|
25
|
+
|
26
|
+
spec.add_development_dependency "pry"
|
27
|
+
spec.add_development_dependency "rspec"
|
28
|
+
spec.add_development_dependency "rake"
|
29
|
+
spec.add_development_dependency "rr"
|
30
|
+
spec.add_development_dependency "simplecov"
|
31
|
+
spec.add_development_dependency "timecop"
|
32
|
+
end
|
metadata
ADDED
@@ -0,0 +1,191 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: openxml-xlsx
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Bob Lail
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-09-07 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: nokogiri
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: open_xml_package
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.1.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.1.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: pry
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rr
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: simplecov
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: timecop
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
description: Create Microsoft Excel (.xlsx) files.
|
126
|
+
email:
|
127
|
+
- bob.lail@cph.org
|
128
|
+
executables: []
|
129
|
+
extensions: []
|
130
|
+
extra_rdoc_files: []
|
131
|
+
files:
|
132
|
+
- ".gitignore"
|
133
|
+
- Gemfile
|
134
|
+
- Gemfile.lock
|
135
|
+
- LICENSE.txt
|
136
|
+
- Rakefile
|
137
|
+
- bin/console
|
138
|
+
- bin/setup
|
139
|
+
- example
|
140
|
+
- lib/xlsx.rb
|
141
|
+
- lib/xlsx/elements.rb
|
142
|
+
- lib/xlsx/elements/alignment.rb
|
143
|
+
- lib/xlsx/elements/border.rb
|
144
|
+
- lib/xlsx/elements/border_component.rb
|
145
|
+
- lib/xlsx/elements/border_style.rb
|
146
|
+
- lib/xlsx/elements/cell.rb
|
147
|
+
- lib/xlsx/elements/defined_name.rb
|
148
|
+
- lib/xlsx/elements/font.rb
|
149
|
+
- lib/xlsx/elements/implied_number_format.rb
|
150
|
+
- lib/xlsx/elements/indexed_color.rb
|
151
|
+
- lib/xlsx/elements/number_format.rb
|
152
|
+
- lib/xlsx/elements/pattern_fill.rb
|
153
|
+
- lib/xlsx/elements/relationship.rb
|
154
|
+
- lib/xlsx/elements/row.rb
|
155
|
+
- lib/xlsx/elements/style.rb
|
156
|
+
- lib/xlsx/elements/table_column.rb
|
157
|
+
- lib/xlsx/elements/theme_color.rb
|
158
|
+
- lib/xlsx/package.rb
|
159
|
+
- lib/xlsx/parts.rb
|
160
|
+
- lib/xlsx/parts/shared_strings.rb
|
161
|
+
- lib/xlsx/parts/stylesheet.rb
|
162
|
+
- lib/xlsx/parts/table.rb
|
163
|
+
- lib/xlsx/parts/workbook.rb
|
164
|
+
- lib/xlsx/parts/worksheet.rb
|
165
|
+
- lib/xlsx/version.rb
|
166
|
+
- xlsx.gemspec
|
167
|
+
homepage: https://github.com/concordia-publishing-house/xlsx
|
168
|
+
licenses:
|
169
|
+
- MIT
|
170
|
+
metadata: {}
|
171
|
+
post_install_message:
|
172
|
+
rdoc_options: []
|
173
|
+
require_paths:
|
174
|
+
- lib
|
175
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
176
|
+
requirements:
|
177
|
+
- - "~>"
|
178
|
+
- !ruby/object:Gem::Version
|
179
|
+
version: '2.0'
|
180
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
181
|
+
requirements:
|
182
|
+
- - ">="
|
183
|
+
- !ruby/object:Gem::Version
|
184
|
+
version: '0'
|
185
|
+
requirements: []
|
186
|
+
rubyforge_project:
|
187
|
+
rubygems_version: 2.2.2
|
188
|
+
signing_key:
|
189
|
+
specification_version: 4
|
190
|
+
summary: Using a simple API, create xlsx files programmatically
|
191
|
+
test_files: []
|