kmadej_fast_excel_fork 0.2.2
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 +13 -0
- data/.travis.yml +28 -0
- data/CHANGELOG.md +13 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +70 -0
- data/Makefile +14 -0
- data/README.md +95 -0
- data/Rakefile +24 -0
- data/appveyor.yml +25 -0
- data/benchmarks/1k_rows.rb +59 -0
- data/benchmarks/20k_rows.rb +26 -0
- data/benchmarks/init.rb +59 -0
- data/benchmarks/memory.rb +49 -0
- data/examples/example.rb +42 -0
- data/examples/example_align.rb +23 -0
- data/examples/example_chart.rb +21 -0
- data/examples/example_colors.rb +37 -0
- data/examples/example_formula.rb +18 -0
- data/examples/example_image.rb +13 -0
- data/examples/example_styles.rb +27 -0
- data/examples/logo.png +0 -0
- data/extconf.rb +0 -0
- data/fast_excel.gemspec +20 -0
- data/lib/fast_excel.rb +600 -0
- data/lib/fast_excel/binding.rb +2819 -0
- data/lib/fast_excel/binding/chart.rb +2666 -0
- data/lib/fast_excel/binding/format.rb +1177 -0
- data/lib/fast_excel/binding/workbook.rb +338 -0
- data/lib/fast_excel/binding/worksheet.rb +1555 -0
- data/libxlsxwriter/.gitignore +49 -0
- data/libxlsxwriter/.indent.pro +125 -0
- data/libxlsxwriter/.travis.yml +25 -0
- data/libxlsxwriter/CONTRIBUTING.md +226 -0
- data/libxlsxwriter/Changes.txt +557 -0
- data/libxlsxwriter/LICENSE.txt +89 -0
- data/libxlsxwriter/Makefile +156 -0
- data/libxlsxwriter/Readme.md +78 -0
- data/libxlsxwriter/cocoapods/libxlsxwriter-umbrella.h +30 -0
- data/libxlsxwriter/cocoapods/libxlsxwriter.modulemap +7 -0
- data/libxlsxwriter/include/xlsxwriter.h +23 -0
- data/libxlsxwriter/include/xlsxwriter/app.h +79 -0
- data/libxlsxwriter/include/xlsxwriter/chart.h +3476 -0
- data/libxlsxwriter/include/xlsxwriter/common.h +372 -0
- data/libxlsxwriter/include/xlsxwriter/content_types.h +74 -0
- data/libxlsxwriter/include/xlsxwriter/core.h +51 -0
- data/libxlsxwriter/include/xlsxwriter/custom.h +52 -0
- data/libxlsxwriter/include/xlsxwriter/drawing.h +111 -0
- data/libxlsxwriter/include/xlsxwriter/format.h +1214 -0
- data/libxlsxwriter/include/xlsxwriter/hash_table.h +76 -0
- data/libxlsxwriter/include/xlsxwriter/packager.h +80 -0
- data/libxlsxwriter/include/xlsxwriter/relationships.h +77 -0
- data/libxlsxwriter/include/xlsxwriter/shared_strings.h +83 -0
- data/libxlsxwriter/include/xlsxwriter/styles.h +77 -0
- data/libxlsxwriter/include/xlsxwriter/theme.h +47 -0
- data/libxlsxwriter/include/xlsxwriter/third_party/ioapi.h +214 -0
- data/libxlsxwriter/include/xlsxwriter/third_party/queue.h +694 -0
- data/libxlsxwriter/include/xlsxwriter/third_party/tmpfileplus.h +53 -0
- data/libxlsxwriter/include/xlsxwriter/third_party/tree.h +801 -0
- data/libxlsxwriter/include/xlsxwriter/third_party/zip.h +375 -0
- data/libxlsxwriter/include/xlsxwriter/utility.h +166 -0
- data/libxlsxwriter/include/xlsxwriter/workbook.h +757 -0
- data/libxlsxwriter/include/xlsxwriter/worksheet.h +2641 -0
- data/libxlsxwriter/include/xlsxwriter/xmlwriter.h +178 -0
- data/libxlsxwriter/lib/.gitignore +0 -0
- data/libxlsxwriter/libxlsxwriter.podspec +47 -0
- data/libxlsxwriter/src/Makefile +130 -0
- data/libxlsxwriter/src/app.c +443 -0
- data/libxlsxwriter/src/chart.c +6346 -0
- data/libxlsxwriter/src/content_types.c +345 -0
- data/libxlsxwriter/src/core.c +293 -0
- data/libxlsxwriter/src/custom.c +224 -0
- data/libxlsxwriter/src/drawing.c +746 -0
- data/libxlsxwriter/src/format.c +729 -0
- data/libxlsxwriter/src/hash_table.c +223 -0
- data/libxlsxwriter/src/packager.c +948 -0
- data/libxlsxwriter/src/relationships.c +245 -0
- data/libxlsxwriter/src/shared_strings.c +266 -0
- data/libxlsxwriter/src/styles.c +1088 -0
- data/libxlsxwriter/src/theme.c +348 -0
- data/libxlsxwriter/src/utility.c +515 -0
- data/libxlsxwriter/src/workbook.c +1930 -0
- data/libxlsxwriter/src/worksheet.c +5022 -0
- data/libxlsxwriter/src/xmlwriter.c +355 -0
- data/libxlsxwriter/third_party/minizip/Makefile +44 -0
- data/libxlsxwriter/third_party/minizip/Makefile.am +45 -0
- data/libxlsxwriter/third_party/minizip/Makefile.orig +25 -0
- data/libxlsxwriter/third_party/minizip/MiniZip64_Changes.txt +6 -0
- data/libxlsxwriter/third_party/minizip/MiniZip64_info.txt +74 -0
- data/libxlsxwriter/third_party/minizip/README.txt +5 -0
- data/libxlsxwriter/third_party/minizip/configure.ac +32 -0
- data/libxlsxwriter/third_party/minizip/crypt.h +131 -0
- data/libxlsxwriter/third_party/minizip/ioapi.c +247 -0
- data/libxlsxwriter/third_party/minizip/ioapi.h +208 -0
- data/libxlsxwriter/third_party/minizip/iowin32.c +456 -0
- data/libxlsxwriter/third_party/minizip/iowin32.h +28 -0
- data/libxlsxwriter/third_party/minizip/make_vms.com +25 -0
- data/libxlsxwriter/third_party/minizip/miniunz.c +660 -0
- data/libxlsxwriter/third_party/minizip/miniunzip.1 +63 -0
- data/libxlsxwriter/third_party/minizip/minizip.1 +46 -0
- data/libxlsxwriter/third_party/minizip/minizip.c +520 -0
- data/libxlsxwriter/third_party/minizip/minizip.pc.in +12 -0
- data/libxlsxwriter/third_party/minizip/mztools.c +291 -0
- data/libxlsxwriter/third_party/minizip/mztools.h +37 -0
- data/libxlsxwriter/third_party/minizip/unzip.c +2125 -0
- data/libxlsxwriter/third_party/minizip/unzip.h +437 -0
- data/libxlsxwriter/third_party/minizip/zip.c +2007 -0
- data/libxlsxwriter/third_party/minizip/zip.h +367 -0
- data/libxlsxwriter/third_party/tmpfileplus/Makefile +42 -0
- data/libxlsxwriter/third_party/tmpfileplus/tmpfileplus.c +342 -0
- data/libxlsxwriter/third_party/tmpfileplus/tmpfileplus.h +53 -0
- data/libxlsxwriter/version.txt +1 -0
- data/test/date_test.rb +22 -0
- data/test/default_format_test.rb +19 -0
- data/test/format_test.rb +171 -0
- data/test/test_helper.rb +52 -0
- data/test/tmpfile_test.rb +23 -0
- data/test/worksheet_test.rb +86 -0
- metadata +182 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
require_relative 'init'
|
|
2
|
+
|
|
3
|
+
HEADERS = ["id", "name", "age", "date", "random"]
|
|
4
|
+
|
|
5
|
+
DATA = []
|
|
6
|
+
10_000.times do |n|
|
|
7
|
+
DATA << [n, "String string #{n}" * 5, (n * rand * 10).round, Time.at(n * 1000 + 1492922688), n * 100]
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
puts "warm up..."
|
|
11
|
+
write_fast_excel_20k
|
|
12
|
+
write_axlsx_20k
|
|
13
|
+
write_xlsx_20k
|
|
14
|
+
|
|
15
|
+
DATA.clear
|
|
16
|
+
50_000.times do |n|
|
|
17
|
+
DATA << [n, "String string #{n}" * 5, (n * rand * 10).round, Time.at(n * 1000 + 1492922688), n * 100]
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
GC.start
|
|
21
|
+
sleep 5
|
|
22
|
+
|
|
23
|
+
def measure_memory(title)
|
|
24
|
+
puts "Running test: #{title}"
|
|
25
|
+
recorder = ProcessMemory.start_recording
|
|
26
|
+
yield
|
|
27
|
+
puts recorder.print("Done!")
|
|
28
|
+
recorder.stop
|
|
29
|
+
puts recorder.report_per_second_pretty
|
|
30
|
+
puts
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
measure_memory("FastExcel") do
|
|
34
|
+
write_fast_excel_20k
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
GC.start
|
|
38
|
+
sleep 5
|
|
39
|
+
|
|
40
|
+
measure_memory("Axlsx") do
|
|
41
|
+
write_axlsx_20k
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
GC.start
|
|
45
|
+
sleep 5
|
|
46
|
+
|
|
47
|
+
measure_memory("write_xlsx") do
|
|
48
|
+
write_xlsx_20k
|
|
49
|
+
end
|
data/examples/example.rb
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
require_relative '../lib/fast_excel'
|
|
2
|
+
|
|
3
|
+
workbook = FastExcel.open("example.xlsx", constant_memory: true)
|
|
4
|
+
|
|
5
|
+
workbook.default_format.set(
|
|
6
|
+
font_size: 0, # user's default
|
|
7
|
+
#font_family: "Arial"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
# pp workbook.default_format
|
|
11
|
+
|
|
12
|
+
worksheet = workbook.add_worksheet("Payments Report")
|
|
13
|
+
|
|
14
|
+
bold = workbook.bold_cell_format
|
|
15
|
+
worksheet.set_column(0, 0, FastExcel::DEF_COL_WIDTH, bold)
|
|
16
|
+
|
|
17
|
+
price = workbook.number_format("#,##0.00")
|
|
18
|
+
worksheet.set_column(1, 1, 20, price)
|
|
19
|
+
|
|
20
|
+
date_format = workbook.number_format("[$-409]m/d/yy h:mm AM/PM;@")
|
|
21
|
+
worksheet.set_column(2, 2, 20, date_format)
|
|
22
|
+
|
|
23
|
+
worksheet.write_row(0, ["message", "price", "date"], bold)
|
|
24
|
+
|
|
25
|
+
for i in 1..1000
|
|
26
|
+
worksheet.write_row(i, ["Hello", (rand * 10_000_000).round(2), Time.now])
|
|
27
|
+
|
|
28
|
+
# Or manually
|
|
29
|
+
# worksheet.write_string(i, 0, "Hello", nil)
|
|
30
|
+
# worksheet.write_number(i, 1, (rand * 10_000_000).round(2), nil)
|
|
31
|
+
# date = Libxlsxwriter::Datetime.new
|
|
32
|
+
# date[:year] = 2017
|
|
33
|
+
# date[:month] = 2
|
|
34
|
+
# date[:day] = 24
|
|
35
|
+
# date[:hour] = i % 24
|
|
36
|
+
# date[:min] = i % 60
|
|
37
|
+
# date[:sec] = i % 60
|
|
38
|
+
# worksheet.write_datetime(i, 2, date, nil)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
workbook.close
|
|
42
|
+
puts "Saved to file example.xlsx"
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require_relative '../lib/fast_excel'
|
|
2
|
+
|
|
3
|
+
workbook = FastExcel.open("example_align.xlsx", constant_memory: true)
|
|
4
|
+
|
|
5
|
+
worksheet = workbook.add_worksheet
|
|
6
|
+
|
|
7
|
+
row_format = workbook.add_format
|
|
8
|
+
|
|
9
|
+
row_format.align = {h: :center, v: :center}
|
|
10
|
+
# Can also be called as:
|
|
11
|
+
# row_format.align = :align_center
|
|
12
|
+
# row_format.align = :align_vertical_center
|
|
13
|
+
|
|
14
|
+
print "Align set as: "
|
|
15
|
+
p row_format.align # => {horizontal: :align_center, vertical: :align_vertical_center}
|
|
16
|
+
|
|
17
|
+
worksheet.set_column_width(0, 30)
|
|
18
|
+
worksheet.set_row(0, 30, row_format)
|
|
19
|
+
|
|
20
|
+
worksheet.write_row(0, ["Hello"])
|
|
21
|
+
|
|
22
|
+
workbook.close
|
|
23
|
+
puts "Saved to file example_align.xlsx"
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require_relative '../lib/fast_excel'
|
|
2
|
+
|
|
3
|
+
workbook = FastExcel.open("example_chart.xlsx", constant_memory: true)
|
|
4
|
+
worksheet = workbook.add_worksheet
|
|
5
|
+
|
|
6
|
+
for i in 0..5
|
|
7
|
+
for n in 0..3
|
|
8
|
+
worksheet.write_number(i, n, (i + 1) * (n + 1), nil)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
chart = workbook.add_chart(Libxlsxwriter::enum_type(:chart_type)[:column])
|
|
13
|
+
|
|
14
|
+
chart.add_series("Bob", "Sheet1!$A$1:$A$5")
|
|
15
|
+
chart.add_series("Alice", "Sheet1!$B$1:$B$5")
|
|
16
|
+
chart.add_series("Montgomery", "Sheet1!$C$1:$C$5")
|
|
17
|
+
|
|
18
|
+
worksheet.insert_chart(1, 7, chart)
|
|
19
|
+
|
|
20
|
+
workbook.close
|
|
21
|
+
puts "Saved to file example_chart.xlsx"
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
require_relative '../lib/fast_excel'
|
|
2
|
+
|
|
3
|
+
workbook = FastExcel.open("example_colors.xlsx", constant_memory: true)
|
|
4
|
+
|
|
5
|
+
worksheet = workbook.add_worksheet
|
|
6
|
+
|
|
7
|
+
color_format = workbook.add_format
|
|
8
|
+
|
|
9
|
+
# We can use color names as string and symbols, color hex codes and color hex numbers
|
|
10
|
+
|
|
11
|
+
color_format.set(
|
|
12
|
+
font_color: '9900FF',
|
|
13
|
+
bg_color: '#FFAAAA',
|
|
14
|
+
|
|
15
|
+
border_bottom: :medium,
|
|
16
|
+
border_bottom_color: 'green',
|
|
17
|
+
|
|
18
|
+
border_left: :slant_dash_dot,
|
|
19
|
+
border_left_color: 0x00FF00,
|
|
20
|
+
|
|
21
|
+
border_right: :double,
|
|
22
|
+
border_right_color: :crimson,
|
|
23
|
+
|
|
24
|
+
border_top: :border_hair,
|
|
25
|
+
border_top_color: :medium_blue
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
# Possible border styles:
|
|
29
|
+
# [:none, :thin, :medium, :dashed, :dotted, :thick, :double, :hair, :medium_dashed,
|
|
30
|
+
# :dash_dot, :medium_dash_dot, :dash_dot_dot, :medium_dash_dot_dot, :slant_dash_dot]
|
|
31
|
+
|
|
32
|
+
worksheet.set_column_width(1, 30)
|
|
33
|
+
|
|
34
|
+
worksheet.write_value(1, 1, "Hello", color_format)
|
|
35
|
+
|
|
36
|
+
workbook.close
|
|
37
|
+
puts "Saved to file example_colors.xlsx"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require_relative '../lib/fast_excel'
|
|
2
|
+
|
|
3
|
+
workbook = FastExcel.open("example_formula.xlsx", constant_memory: false)
|
|
4
|
+
|
|
5
|
+
worksheet = workbook.add_worksheet
|
|
6
|
+
|
|
7
|
+
worksheet.write_row(0, ["Item", "Weight"])
|
|
8
|
+
worksheet.write_row(1, ["Laptop", 1.37])
|
|
9
|
+
worksheet.write_row(2, ["Phone", 0.138])
|
|
10
|
+
worksheet.write_row(3, ["Mouse", 0.099])
|
|
11
|
+
worksheet.write_row(4, ["Speaker", 2.5])
|
|
12
|
+
worksheet.write_row(5, ["Camera", 0.383])
|
|
13
|
+
worksheet.write_row(6, ["Total", FastExcel::Formula.new("SUM(B2:B6)")], workbook.bold_cell_format)
|
|
14
|
+
|
|
15
|
+
bold = workbook.bold_cell_format
|
|
16
|
+
|
|
17
|
+
workbook.close
|
|
18
|
+
puts "Saved to file example_formula.xlsx"
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require_relative '../lib/fast_excel'
|
|
2
|
+
|
|
3
|
+
workbook = FastExcel.open("example_image.xlsx", constant_memory: false)
|
|
4
|
+
worksheet = workbook.add_worksheet
|
|
5
|
+
|
|
6
|
+
img_options = Libxlsxwriter::ImageOptions.new
|
|
7
|
+
img_options[:x_offset] = 0
|
|
8
|
+
img_options[:y_offset] = 0
|
|
9
|
+
|
|
10
|
+
worksheet.insert_image_opt(3, 3, "examples/logo.png", img_options)
|
|
11
|
+
|
|
12
|
+
workbook.close
|
|
13
|
+
puts "Saved to file example_image.xlsx"
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require_relative '../lib/fast_excel'
|
|
2
|
+
|
|
3
|
+
workbook = FastExcel.open("example_styles.xlsx", constant_memory: true)
|
|
4
|
+
|
|
5
|
+
#workbook.default_format.set(
|
|
6
|
+
# font_size: 0, # user's default
|
|
7
|
+
# #font_family: "Arial"
|
|
8
|
+
#)
|
|
9
|
+
|
|
10
|
+
worksheet = workbook.add_worksheet
|
|
11
|
+
|
|
12
|
+
worksheet.set_columns_width(0, 11, 11)
|
|
13
|
+
|
|
14
|
+
worksheet.write_value(0, 0, "Bold", workbook.add_format(bold: true))
|
|
15
|
+
worksheet.write_value(0, 1, "Italic", workbook.add_format(italic: true))
|
|
16
|
+
worksheet.write_value(0, 2, "Underline", workbook.add_format(underline: :underline_single))
|
|
17
|
+
worksheet.write_value(0, 3, "Double line", workbook.add_format(underline: :underline_double))
|
|
18
|
+
worksheet.write_value(0, 4, "Indent", workbook.add_format(indent: 1))
|
|
19
|
+
worksheet.write_value(0, 5, "Border", workbook.add_format(border: :border_thin))
|
|
20
|
+
worksheet.write_value(0, 6, "Border2", workbook.add_format(border: :border_medium))
|
|
21
|
+
worksheet.write_value(0, 7, "Pattern", workbook.add_format(pattern: :pattern_light_up, bg_color: :yellow))
|
|
22
|
+
worksheet.write_value(0, 8, "Script", workbook.add_format(font_script: :font_subscript))
|
|
23
|
+
worksheet.write_value(0, 9, "Strike", workbook.add_format(font_strikeout: true))
|
|
24
|
+
worksheet.write_value(0, 10, "Shaddow", workbook.add_format(font_shadow: true))
|
|
25
|
+
|
|
26
|
+
workbook.close
|
|
27
|
+
puts "Saved to file example_styles.xlsx"
|
data/examples/logo.png
ADDED
|
Binary file
|
data/extconf.rb
ADDED
|
File without changes
|
data/fast_excel.gemspec
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Gem::Specification.new do |s|
|
|
2
|
+
s.name = "kmadej_fast_excel_fork"
|
|
3
|
+
s.version = "0.2.2"
|
|
4
|
+
s.author = ["Pavel Evstigneev"]
|
|
5
|
+
s.email = ["pavel.evst@gmail.com"]
|
|
6
|
+
s.homepage = "https://github.com/paxa/fast_excel"
|
|
7
|
+
s.summary = %q{Ultra Fast Excel Writter}
|
|
8
|
+
s.description = "Wrapper for libxlsxwriter using ffi"
|
|
9
|
+
s.license = 'MIT'
|
|
10
|
+
s.has_rdoc = false
|
|
11
|
+
s.required_ruby_version = '~> 2.0'
|
|
12
|
+
|
|
13
|
+
s.files = `git ls-files`.split("\n")
|
|
14
|
+
s.test_files = []
|
|
15
|
+
|
|
16
|
+
s.require_paths = ["lib"]
|
|
17
|
+
s.extensions = ["extconf.rb"]
|
|
18
|
+
|
|
19
|
+
s.add_runtime_dependency "ffi", ["> 1.9", "< 2"]
|
|
20
|
+
end
|
data/lib/fast_excel.rb
ADDED
|
@@ -0,0 +1,600 @@
|
|
|
1
|
+
require_relative './fast_excel/binding'
|
|
2
|
+
|
|
3
|
+
module FastExcel
|
|
4
|
+
|
|
5
|
+
class Formula
|
|
6
|
+
attr_accessor :fml
|
|
7
|
+
def initialize(fml)
|
|
8
|
+
@fml = fml
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
DEF_COL_WIDTH = 8.43
|
|
13
|
+
|
|
14
|
+
def self.open(filename = nil, constant_memory: false, default_format: nil)
|
|
15
|
+
tmp_file = false
|
|
16
|
+
unless filename
|
|
17
|
+
require 'tmpdir'
|
|
18
|
+
filename = "#{Dir.mktmpdir}/fast_excel.xlsx"
|
|
19
|
+
tmp_file = true
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
unless filename
|
|
23
|
+
raise ArgumentError, "filename is required"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
filename = filename.to_s if defined?(Pathname) && filename.is_a?(Pathname)
|
|
27
|
+
|
|
28
|
+
workbook = if constant_memory
|
|
29
|
+
opt = Libxlsxwriter::WorkbookOptions.new
|
|
30
|
+
opt[:constant_memory] = 1
|
|
31
|
+
Libxlsxwriter.workbook_new_opt(filename, opt)
|
|
32
|
+
else
|
|
33
|
+
Libxlsxwriter.workbook_new(filename)
|
|
34
|
+
end
|
|
35
|
+
result = Libxlsxwriter::Workbook.new(workbook)
|
|
36
|
+
|
|
37
|
+
if default_format
|
|
38
|
+
raise "default_format argument must be a hash" unless default_format.is_a?(Hash)
|
|
39
|
+
result.default_format.set(default_format)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
result.tmp_file = tmp_file
|
|
43
|
+
result.filename = filename
|
|
44
|
+
result
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Creates internal Libxlsxwriter::Datetime from Datetime object
|
|
48
|
+
def self.lxw_datetime(time)
|
|
49
|
+
date = Libxlsxwriter::Datetime.new
|
|
50
|
+
date[:year] = time.year
|
|
51
|
+
date[:month] = time.month
|
|
52
|
+
date[:day] = time.day
|
|
53
|
+
date[:hour] = time.hour
|
|
54
|
+
date[:min] = time.minute
|
|
55
|
+
date[:sec] = time.second
|
|
56
|
+
date
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Creates internal Libxlsxwriter::Datetime from Time object
|
|
60
|
+
def self.lxw_time(time)
|
|
61
|
+
date = Libxlsxwriter::Datetime.new
|
|
62
|
+
date[:year] = time.year
|
|
63
|
+
date[:month] = time.month
|
|
64
|
+
date[:day] = time.day
|
|
65
|
+
date[:hour] = time.hour
|
|
66
|
+
date[:min] = time.min
|
|
67
|
+
date[:sec] = time.sec
|
|
68
|
+
date
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# seconds in 1 day
|
|
72
|
+
XLSX_DATE_DAY = 86400.0
|
|
73
|
+
|
|
74
|
+
# days between 1970-jan-01 and 1900-jan-01
|
|
75
|
+
XLSX_DATE_EPOCH_DIFF = 25569
|
|
76
|
+
|
|
77
|
+
# Convert time to number of days, and change beginning point from 1st jan 1970 to 1st jan 1900
|
|
78
|
+
# Offset argument should be number of seconds, if not specified then it will use Time.zone.utc_offset || 0
|
|
79
|
+
#
|
|
80
|
+
# https://support.microsoft.com/en-us/help/214330/differences-between-the-1900-and-the-1904-date-system-in-excel
|
|
81
|
+
def self.date_num(time, offset = nil)
|
|
82
|
+
unless offset
|
|
83
|
+
# Try use Rails' app timezone
|
|
84
|
+
if Time.respond_to?(:zone)
|
|
85
|
+
offset = Time.zone.utc_offset
|
|
86
|
+
else
|
|
87
|
+
offset = 0 # rollback to UTC
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
time.to_f / XLSX_DATE_DAY + XLSX_DATE_EPOCH_DIFF + offset / XLSX_DATE_DAY
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def self.print_ffi_obj(value)
|
|
95
|
+
puts "#{value.class}"
|
|
96
|
+
value.members.each do |key|
|
|
97
|
+
field_val = if value[key].is_a?(FFI::Pointer) && value[key].null? || value[key].nil?
|
|
98
|
+
"nil"
|
|
99
|
+
elsif value[key].is_a?(FFI::StructLayout::CharArray)
|
|
100
|
+
value[key].to_str.inspect
|
|
101
|
+
elsif value[key].is_a?(String)
|
|
102
|
+
value[key].inspect
|
|
103
|
+
elsif value[key].is_a?(Symbol)
|
|
104
|
+
value[key].inspect
|
|
105
|
+
else
|
|
106
|
+
value[key]
|
|
107
|
+
end
|
|
108
|
+
puts "* #{key}: #{field_val}"
|
|
109
|
+
end
|
|
110
|
+
nil
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
COLOR_ENUM = Libxlsxwriter.enum_type(:defined_colors)
|
|
115
|
+
EXTRA_COLORS = {
|
|
116
|
+
alice_blue: 0xF0F8FF,
|
|
117
|
+
antique_white: 0xFAEBD7,
|
|
118
|
+
aqua: 0x00FFFF,
|
|
119
|
+
aquamarine: 0x7FFFD4,
|
|
120
|
+
azure: 0xF0FFFF,
|
|
121
|
+
beige: 0xF5F5DC,
|
|
122
|
+
bisque: 0xFFE4C4,
|
|
123
|
+
black: 0x000000,
|
|
124
|
+
blanched_almond: 0xFFEBCD,
|
|
125
|
+
blue: 0x0000FF,
|
|
126
|
+
blue_violet: 0x8A2BE2,
|
|
127
|
+
brown: 0xA52A2A,
|
|
128
|
+
burly_wood: 0xDEB887,
|
|
129
|
+
cadet_blue: 0x5F9EA0,
|
|
130
|
+
chartreuse: 0x7FFF00,
|
|
131
|
+
chocolate: 0xD2691E,
|
|
132
|
+
coral: 0xFF7F50,
|
|
133
|
+
cornflower_blue: 0x6495ED,
|
|
134
|
+
cornsilk: 0xFFF8DC,
|
|
135
|
+
crimson: 0xDC143C,
|
|
136
|
+
cyan: 0x00FFFF,
|
|
137
|
+
dark_blue: 0x00008B,
|
|
138
|
+
dark_cyan: 0x008B8B,
|
|
139
|
+
dark_golden_rod: 0xB8860B,
|
|
140
|
+
dark_gray: 0xA9A9A9,
|
|
141
|
+
dark_grey: 0xA9A9A9,
|
|
142
|
+
dark_green: 0x006400,
|
|
143
|
+
dark_khaki: 0xBDB76B,
|
|
144
|
+
dark_magenta: 0x8B008B,
|
|
145
|
+
dark_olive_green: 0x556B2F,
|
|
146
|
+
dark_orange: 0xFF8C00,
|
|
147
|
+
dark_orchid: 0x9932CC,
|
|
148
|
+
dark_red: 0x8B0000,
|
|
149
|
+
dark_salmon: 0xE9967A,
|
|
150
|
+
dark_sea_green: 0x8FBC8F,
|
|
151
|
+
dark_slate_blue: 0x483D8B,
|
|
152
|
+
dark_slate_gray: 0x2F4F4F,
|
|
153
|
+
dark_slate_grey: 0x2F4F4F,
|
|
154
|
+
dark_turquoise: 0x00CED1,
|
|
155
|
+
dark_violet: 0x9400D3,
|
|
156
|
+
deep_pink: 0xFF1493,
|
|
157
|
+
deep_sky_blue: 0x00BFFF,
|
|
158
|
+
dim_gray: 0x696969,
|
|
159
|
+
dim_grey: 0x696969,
|
|
160
|
+
dodger_blue: 0x1E90FF,
|
|
161
|
+
fire_brick: 0xB22222,
|
|
162
|
+
floral_white: 0xFFFAF0,
|
|
163
|
+
forest_green: 0x228B22,
|
|
164
|
+
fuchsia: 0xFF00FF,
|
|
165
|
+
gainsboro: 0xDCDCDC,
|
|
166
|
+
ghost_white: 0xF8F8FF,
|
|
167
|
+
gold: 0xFFD700,
|
|
168
|
+
golden_rod: 0xDAA520,
|
|
169
|
+
gray: 0x808080,
|
|
170
|
+
grey: 0x808080,
|
|
171
|
+
green: 0x008000,
|
|
172
|
+
green_yellow: 0xADFF2F,
|
|
173
|
+
honey_dew: 0xF0FFF0,
|
|
174
|
+
hot_pink: 0xFF69B4,
|
|
175
|
+
indian_red: 0xCD5C5C,
|
|
176
|
+
indigo: 0x4B0082,
|
|
177
|
+
ivory: 0xFFFFF0,
|
|
178
|
+
khaki: 0xF0E68C,
|
|
179
|
+
lavender: 0xE6E6FA,
|
|
180
|
+
lavender_blush: 0xFFF0F5,
|
|
181
|
+
lawn_green: 0x7CFC00,
|
|
182
|
+
lemon_chiffon: 0xFFFACD,
|
|
183
|
+
light_blue: 0xADD8E6,
|
|
184
|
+
light_coral: 0xF08080,
|
|
185
|
+
light_cyan: 0xE0FFFF,
|
|
186
|
+
light_golden_rod_yellow: 0xFAFAD2,
|
|
187
|
+
light_gray: 0xD3D3D3,
|
|
188
|
+
light_grey: 0xD3D3D3,
|
|
189
|
+
light_green: 0x90EE90,
|
|
190
|
+
light_pink: 0xFFB6C1,
|
|
191
|
+
light_salmon: 0xFFA07A,
|
|
192
|
+
light_sea_green: 0x20B2AA,
|
|
193
|
+
light_sky_blue: 0x87CEFA,
|
|
194
|
+
light_slate_gray: 0x778899,
|
|
195
|
+
light_slate_grey: 0x778899,
|
|
196
|
+
light_steel_blue: 0xB0C4DE,
|
|
197
|
+
light_yellow: 0xFFFFE0,
|
|
198
|
+
lime: 0x00FF00,
|
|
199
|
+
lime_green: 0x32CD32,
|
|
200
|
+
linen: 0xFAF0E6,
|
|
201
|
+
magenta: 0xFF00FF,
|
|
202
|
+
maroon: 0x800000,
|
|
203
|
+
medium_aqua_marine: 0x66CDAA,
|
|
204
|
+
medium_blue: 0x0000CD,
|
|
205
|
+
medium_orchid: 0xBA55D3,
|
|
206
|
+
medium_purple: 0x9370DB,
|
|
207
|
+
medium_sea_green: 0x3CB371,
|
|
208
|
+
medium_slate_blue: 0x7B68EE,
|
|
209
|
+
medium_spring_green: 0x00FA9A,
|
|
210
|
+
medium_turquoise: 0x48D1CC,
|
|
211
|
+
medium_violet_red: 0xC71585,
|
|
212
|
+
midnight_blue: 0x191970,
|
|
213
|
+
mint_cream: 0xF5FFFA,
|
|
214
|
+
misty_rose: 0xFFE4E1,
|
|
215
|
+
moccasin: 0xFFE4B5,
|
|
216
|
+
navajo_white: 0xFFDEAD,
|
|
217
|
+
navy: 0x000080,
|
|
218
|
+
old_lace: 0xFDF5E6,
|
|
219
|
+
olive: 0x808000,
|
|
220
|
+
olive_drab: 0x6B8E23,
|
|
221
|
+
orange: 0xFFA500,
|
|
222
|
+
orange_red: 0xFF4500,
|
|
223
|
+
orchid: 0xDA70D6,
|
|
224
|
+
pale_golden_rod: 0xEEE8AA,
|
|
225
|
+
pale_green: 0x98FB98,
|
|
226
|
+
pale_turquoise: 0xAFEEEE,
|
|
227
|
+
pale_violet_red: 0xDB7093,
|
|
228
|
+
papaya_whip: 0xFFEFD5,
|
|
229
|
+
peach_puff: 0xFFDAB9,
|
|
230
|
+
peru: 0xCD853F,
|
|
231
|
+
pink: 0xFFC0CB,
|
|
232
|
+
plum: 0xDDA0DD,
|
|
233
|
+
powder_blue: 0xB0E0E6,
|
|
234
|
+
purple: 0x800080,
|
|
235
|
+
rebecca_purple: 0x663399,
|
|
236
|
+
red: 0xFF0000,
|
|
237
|
+
rosy_brown: 0xBC8F8F,
|
|
238
|
+
royal_blue: 0x4169E1,
|
|
239
|
+
saddle_brown: 0x8B4513,
|
|
240
|
+
salmon: 0xFA8072,
|
|
241
|
+
sandy_brown: 0xF4A460,
|
|
242
|
+
sea_green: 0x2E8B57,
|
|
243
|
+
sea_shell: 0xFFF5EE,
|
|
244
|
+
sienna: 0xA0522D,
|
|
245
|
+
silver: 0xC0C0C0,
|
|
246
|
+
sky_blue: 0x87CEEB,
|
|
247
|
+
slate_blue: 0x6A5ACD,
|
|
248
|
+
slate_gray: 0x708090,
|
|
249
|
+
slate_grey: 0x708090,
|
|
250
|
+
snow: 0xFFFAFA,
|
|
251
|
+
spring_green: 0x00FF7F,
|
|
252
|
+
steel_blue: 0x4682B4,
|
|
253
|
+
tan: 0xD2B48C,
|
|
254
|
+
teal: 0x008080,
|
|
255
|
+
thistle: 0xD8BFD8,
|
|
256
|
+
tomato: 0xFF6347,
|
|
257
|
+
turquoise: 0x40E0D0,
|
|
258
|
+
violet: 0xEE82EE,
|
|
259
|
+
wheat: 0xF5DEB3,
|
|
260
|
+
white: 0xFFFFFF,
|
|
261
|
+
white_smoke: 0xF5F5F5,
|
|
262
|
+
yellow: 0xFFFF00,
|
|
263
|
+
yellow_green: 0x9ACD32
|
|
264
|
+
}.freeze
|
|
265
|
+
|
|
266
|
+
# Convert hex string, color name or hex number to color hex number
|
|
267
|
+
def self.color_to_hex(value)
|
|
268
|
+
orig_value = value
|
|
269
|
+
value = value.to_s if value.is_a?(Symbol)
|
|
270
|
+
|
|
271
|
+
if value.is_a?(String)
|
|
272
|
+
if EXTRA_COLORS[value.to_sym]
|
|
273
|
+
return EXTRA_COLORS[value.to_sym]
|
|
274
|
+
elsif COLOR_ENUM.find(value.to_sym)
|
|
275
|
+
return COLOR_ENUM.find(value.to_sym)
|
|
276
|
+
elsif COLOR_ENUM.find("color_#{value.to_sym}")
|
|
277
|
+
return COLOR_ENUM.find("color_#{value.to_sym}")
|
|
278
|
+
elsif value =~ /^#?(0x)?([\da-f]){6}$/i
|
|
279
|
+
value = value.sub('#', '') if value.start_with?('#')
|
|
280
|
+
return value.start_with?('0x') ? value.to_i(16) : "0x#{value}".to_i(16)
|
|
281
|
+
else
|
|
282
|
+
raise ArgumentError, "Unknown color value #{orig_value.inspect}, expected hex string or color name"
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
return value if value.is_a?(Numeric)
|
|
287
|
+
|
|
288
|
+
raise ArgumentError, "Can not use #{value.class} (#{value.inspect}) for color value, expected String or Hex Number"
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
module AttributeHelper
|
|
292
|
+
def set(values)
|
|
293
|
+
values.each do |key, value|
|
|
294
|
+
if respond_to?("#{key}=")
|
|
295
|
+
send("#{key}=", value)
|
|
296
|
+
elsif respond_to?("set_#{key}=")
|
|
297
|
+
send("set_#{key}=", value)
|
|
298
|
+
else
|
|
299
|
+
self[key] = value
|
|
300
|
+
end
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
self
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
def fields_hash
|
|
307
|
+
res = {}
|
|
308
|
+
members.each do |key|
|
|
309
|
+
#p [key, self[key]]
|
|
310
|
+
res[key] = respond_to?(key) ? send(key) : self[key]
|
|
311
|
+
end
|
|
312
|
+
res
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
def pretty_print(pp)
|
|
316
|
+
pp fields_hash
|
|
317
|
+
end
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
module WorkbookExt
|
|
321
|
+
include AttributeHelper
|
|
322
|
+
attr_accessor :tmp_file, :is_open, :filename
|
|
323
|
+
|
|
324
|
+
def initialize(struct)
|
|
325
|
+
@is_open = true
|
|
326
|
+
super(struct)
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
def add_format(options = nil)
|
|
330
|
+
new_format = super()
|
|
331
|
+
new_format.set(options) if options
|
|
332
|
+
new_format
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
def bold_cell_format
|
|
336
|
+
bold = add_format
|
|
337
|
+
bold.set_bold
|
|
338
|
+
bold
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
# "#,##0.00"
|
|
342
|
+
# "[$-409]m/d/yy h:mm AM/PM;@"
|
|
343
|
+
def number_format(pattern)
|
|
344
|
+
format = add_format
|
|
345
|
+
format.set_num_format(pattern)
|
|
346
|
+
format
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
def add_worksheet(sheetname = nil)
|
|
350
|
+
sheet = super
|
|
351
|
+
sheet.workbook = self
|
|
352
|
+
sheet
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
def close
|
|
356
|
+
@is_open = false
|
|
357
|
+
super
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
def read_string
|
|
361
|
+
close if @is_open
|
|
362
|
+
File.open(filename, 'rb', &:read)
|
|
363
|
+
ensure
|
|
364
|
+
remove_tmp_file
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
def remove_tmp_file
|
|
368
|
+
File.delete(filename) if tmp_file
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
def constant_memory?
|
|
372
|
+
#FastExcel.print_ffi_obj(self[:options])
|
|
373
|
+
@constant_memory ||= self[:options][:constant_memory] != 0
|
|
374
|
+
end
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
module WorksheetExt
|
|
378
|
+
attr_accessor :workbook
|
|
379
|
+
|
|
380
|
+
include AttributeHelper
|
|
381
|
+
|
|
382
|
+
def write_row(row_number, values, formats = nil)
|
|
383
|
+
values.each_with_index do |value, index|
|
|
384
|
+
format = if formats
|
|
385
|
+
formats.is_a?(Array) ? formats[index] : formats
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
write_value(row_number, index, value, format)
|
|
389
|
+
end
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
def write_value(row_number, cell_number, value, format = nil)
|
|
393
|
+
|
|
394
|
+
if workbook.constant_memory? && row_number < last_row_number
|
|
395
|
+
raise ArgumentError, "Can not write to saved row in constant_memory mode (attempted row: #{row_number}, last saved row: #{last_row_number})"
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
if value.is_a?(Numeric)
|
|
399
|
+
write_number(row_number, cell_number, value, format)
|
|
400
|
+
elsif defined?(DateTime) && value.is_a?(DateTime)
|
|
401
|
+
write_datetime(row_number, cell_number, FastExcel.lxw_datetime(value), format)
|
|
402
|
+
elsif value.is_a?(Time)
|
|
403
|
+
write_datetime(row_number, cell_number, FastExcel.lxw_time(value), format)
|
|
404
|
+
elsif value.is_a?(Formula)
|
|
405
|
+
write_formula(row_number, cell_number, value.fml, format)
|
|
406
|
+
else
|
|
407
|
+
write_string(row_number, cell_number, value.to_s, format)
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
@last_row_number = row_number > last_row_number ? row_number : last_row_number
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
def append_row(values, formats = nil)
|
|
414
|
+
increment_last_row_number!
|
|
415
|
+
write_row(last_row_number, values, formats)
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
def last_row_number
|
|
419
|
+
defined?(@last_row_number) ? @last_row_number : -1
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
def increment_last_row_number!
|
|
423
|
+
@last_row_number = last_row_number + 1
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
def set_column(start_col, end_col, width, format = nil)
|
|
427
|
+
super(start_col, end_col, width, format)
|
|
428
|
+
end
|
|
429
|
+
|
|
430
|
+
def set_column_width(col, width)
|
|
431
|
+
set_column(col, col, width, nil)
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
def set_columns_width(start_col, end_col, width)
|
|
435
|
+
set_column(start_col, end_col, width, nil)
|
|
436
|
+
end
|
|
437
|
+
|
|
438
|
+
end
|
|
439
|
+
|
|
440
|
+
module FormatExt
|
|
441
|
+
include AttributeHelper
|
|
442
|
+
|
|
443
|
+
[:font_size, :underline, :font_script, :rotation, :indent, :pattern, :border].each do |prop|
|
|
444
|
+
define_method(prop) do
|
|
445
|
+
self[prop]
|
|
446
|
+
end
|
|
447
|
+
define_method("#{prop}=") do |value|
|
|
448
|
+
send("set_#{prop}", value)
|
|
449
|
+
end
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
[:bold, :italic, :font_outline, :font_shadow, :hidden, :text_wrap, :font_strikeout, :shrink, :text_justlast].each do |prop|
|
|
453
|
+
define_method(prop) do
|
|
454
|
+
self[prop]
|
|
455
|
+
end
|
|
456
|
+
define_method("#{prop}=") do |value|
|
|
457
|
+
value ? send("set_#{prop}") : self[prop] = false
|
|
458
|
+
end
|
|
459
|
+
end
|
|
460
|
+
|
|
461
|
+
[:num_format, :font_name].each do |prop|
|
|
462
|
+
define_method(prop) do
|
|
463
|
+
self[prop].to_ptr.read_string
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
define_method("#{prop}=") do |value|
|
|
467
|
+
send("set_#{prop}", value)
|
|
468
|
+
end
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
ALIGN_ENUM = Libxlsxwriter.enum_type(:format_alignments)
|
|
472
|
+
|
|
473
|
+
# Can be called as:
|
|
474
|
+
#
|
|
475
|
+
# format.align = :align_center
|
|
476
|
+
# format.align = "align_center"
|
|
477
|
+
# format.align = :center
|
|
478
|
+
# format.align = :align_center
|
|
479
|
+
# format.align = {v: "center", h: "center"}
|
|
480
|
+
#
|
|
481
|
+
# Possible values:
|
|
482
|
+
#
|
|
483
|
+
# :align_none, :align_left, :align_center, :align_right, :align_fill, :align_justify,
|
|
484
|
+
# :align_center_across, :align_distributed, :align_vertical_top, :align_vertical_bottom,
|
|
485
|
+
# :align_vertical_center, :align_vertical_justify, :align_vertical_distributed
|
|
486
|
+
#
|
|
487
|
+
def align=(value)
|
|
488
|
+
value = value.to_sym if value.is_a?(String)
|
|
489
|
+
|
|
490
|
+
if value.is_a?(Symbol)
|
|
491
|
+
if ALIGN_ENUM.find(value)
|
|
492
|
+
set_align(value)
|
|
493
|
+
elsif ALIGN_ENUM.find(prefixed = "align_#{value}".to_sym)
|
|
494
|
+
set_align(prefixed)
|
|
495
|
+
else
|
|
496
|
+
raise ArgumentError, "Can not set align = #{value.inspect}, possible values are: #{ALIGN_ENUM.symbols}"
|
|
497
|
+
end
|
|
498
|
+
elsif value.is_a?(Hash)
|
|
499
|
+
if value[:horizontal]
|
|
500
|
+
self.align = "align_#{value[:horizontal].to_s.sub(/^align_/, '')}".to_sym
|
|
501
|
+
end
|
|
502
|
+
if value[:h]
|
|
503
|
+
self.align = "align_#{value[:h].to_s.sub(/^align_/, '')}".to_sym
|
|
504
|
+
end
|
|
505
|
+
if value[:vertical]
|
|
506
|
+
self.align = "align_vertical_#{value[:vertical].to_s.sub(/^align_vertical_/, '')}".to_sym
|
|
507
|
+
end
|
|
508
|
+
if value[:v]
|
|
509
|
+
self.align = "align_vertical_#{value[:v].to_s.sub(/^align_vertical_/, '')}".to_sym
|
|
510
|
+
end
|
|
511
|
+
possible = [:horizontal, :h, :vertical, :v]
|
|
512
|
+
extras = value.keys - possible
|
|
513
|
+
if extras.size > 0
|
|
514
|
+
raise ArgumentError, "Not allowed keys for align: #{extras.inspect}, possible keys: #{possible.inspect}"
|
|
515
|
+
end
|
|
516
|
+
else
|
|
517
|
+
raise ArgumentError, "value must be a symbol or a hash"
|
|
518
|
+
end
|
|
519
|
+
end
|
|
520
|
+
|
|
521
|
+
def align
|
|
522
|
+
{
|
|
523
|
+
horizontal: ALIGN_ENUM.find(self[:text_h_align]),
|
|
524
|
+
vertical: ALIGN_ENUM.find(self[:text_v_align])
|
|
525
|
+
}
|
|
526
|
+
end
|
|
527
|
+
|
|
528
|
+
[:font_color, :bg_color, :fg_color, :bottom_color, :diag_color, :left_color, :right_color, :top_color].each do |prop|
|
|
529
|
+
define_method("#{prop}=") do |value|
|
|
530
|
+
send("set_#{prop}", FastExcel.color_to_hex(value))
|
|
531
|
+
end
|
|
532
|
+
define_method(prop) do
|
|
533
|
+
self[prop]
|
|
534
|
+
end
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
[:bottom_color, :left_color, :right_color, :top_color].each do |prop|
|
|
538
|
+
alias_method :"border_#{prop}=", :"#{prop}="
|
|
539
|
+
alias_method :"border_#{prop}", :"#{prop}"
|
|
540
|
+
end
|
|
541
|
+
|
|
542
|
+
BORDER_ENUM = Libxlsxwriter.enum_type(:format_borders)
|
|
543
|
+
|
|
544
|
+
[:bottom, :diag_border, :left, :right, :top].each do |prop|
|
|
545
|
+
define_method("#{prop}=") do |value|
|
|
546
|
+
|
|
547
|
+
send("set_#{prop}", border_value(value))
|
|
548
|
+
end
|
|
549
|
+
define_method(prop) do
|
|
550
|
+
BORDER_ENUM.find(self[prop])
|
|
551
|
+
end
|
|
552
|
+
|
|
553
|
+
unless prop == :diag_border
|
|
554
|
+
alias_method :"border_#{prop}=", :"#{prop}="
|
|
555
|
+
alias_method :"border_#{prop}", :"#{prop}"
|
|
556
|
+
end
|
|
557
|
+
end
|
|
558
|
+
|
|
559
|
+
def border_value(value)
|
|
560
|
+
# if a number
|
|
561
|
+
return value if value.is_a?(Numeric) && BORDER_ENUM.find(value)
|
|
562
|
+
|
|
563
|
+
orig_value = value
|
|
564
|
+
value = value.to_sym if value.is_a?(String)
|
|
565
|
+
|
|
566
|
+
return BORDER_ENUM.find(value) if BORDER_ENUM.find(value)
|
|
567
|
+
return BORDER_ENUM.find(:"border_#{value}") if BORDER_ENUM.find(:"border_#{value}")
|
|
568
|
+
|
|
569
|
+
short_symbols = BORDER_ENUM.symbols.map {|s| s.to_s.sub(/^border_/, '').to_sym }
|
|
570
|
+
raise ArgumentError, "Unknown value #{orig_value.inspect} for border. Possible values: #{short_symbols}"
|
|
571
|
+
end
|
|
572
|
+
|
|
573
|
+
def set_font_size(value)
|
|
574
|
+
if value < 0
|
|
575
|
+
raise ArgumentError, "font size should be >= 0 (use 0 for user default font size)"
|
|
576
|
+
end
|
|
577
|
+
super(value)
|
|
578
|
+
end
|
|
579
|
+
|
|
580
|
+
def font_family
|
|
581
|
+
font_name
|
|
582
|
+
end
|
|
583
|
+
|
|
584
|
+
def font_family=(value)
|
|
585
|
+
self.font_name = value
|
|
586
|
+
end
|
|
587
|
+
end
|
|
588
|
+
end
|
|
589
|
+
|
|
590
|
+
Libxlsxwriter::Workbook.instance_eval do
|
|
591
|
+
include FastExcel::WorkbookExt
|
|
592
|
+
end
|
|
593
|
+
|
|
594
|
+
Libxlsxwriter::Format.instance_eval do
|
|
595
|
+
include FastExcel::FormatExt
|
|
596
|
+
end
|
|
597
|
+
|
|
598
|
+
Libxlsxwriter::Worksheet.instance_eval do
|
|
599
|
+
include FastExcel::WorksheetExt
|
|
600
|
+
end
|