fast_excel 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +5 -5
  2. data/.dockerignore +2 -0
  3. data/.gitignore +7 -0
  4. data/.travis.yml +44 -0
  5. data/CHANGELOG.md +41 -1
  6. data/Dockerfile.test +16 -0
  7. data/Gemfile +5 -2
  8. data/Gemfile.lock +30 -23
  9. data/LICENSE +21 -0
  10. data/Makefile +13 -0
  11. data/README.md +177 -40
  12. data/Rakefile +16 -0
  13. data/appveyor.yml +25 -0
  14. data/benchmarks/1k_rows.rb +17 -4
  15. data/benchmarks/20k_rows.rb +4 -0
  16. data/benchmarks/auto_width.rb +37 -0
  17. data/benchmarks/init.rb +14 -2
  18. data/benchmarks/memory.rb +8 -0
  19. data/benchmarks/profiler.rb +27 -0
  20. data/benchmarks/write_value.rb +62 -0
  21. data/examples/example.rb +3 -4
  22. data/examples/example_align.rb +23 -0
  23. data/examples/example_auto_width.rb +26 -0
  24. data/examples/example_colors.rb +37 -0
  25. data/examples/example_filters.rb +36 -0
  26. data/examples/example_formula.rb +1 -5
  27. data/examples/example_hyperlink.rb +20 -0
  28. data/examples/example_image.rb +1 -1
  29. data/examples/example_styles.rb +27 -0
  30. data/examples/logo.png +0 -0
  31. data/ext/fast_excel/extconf.rb +3 -0
  32. data/ext/fast_excel/text_width_ext.c +460 -0
  33. data/fast_excel.gemspec +2 -3
  34. data/letters.html +114 -0
  35. data/lib/fast_excel.rb +455 -78
  36. data/lib/fast_excel/binding.rb +31 -21
  37. data/lib/fast_excel/binding/chart.rb +20 -1
  38. data/lib/fast_excel/binding/format.rb +11 -4
  39. data/lib/fast_excel/binding/workbook.rb +10 -2
  40. data/lib/fast_excel/binding/worksheet.rb +44 -27
  41. data/libxlsxwriter/.gitignore +1 -0
  42. data/libxlsxwriter/.indent.pro +8 -0
  43. data/libxlsxwriter/.travis.yml +12 -0
  44. data/libxlsxwriter/CMakeLists.txt +338 -0
  45. data/libxlsxwriter/CONTRIBUTING.md +1 -1
  46. data/libxlsxwriter/Changes.txt +162 -0
  47. data/libxlsxwriter/LICENSE.txt +65 -4
  48. data/libxlsxwriter/Makefile +33 -11
  49. data/libxlsxwriter/Readme.md +3 -1
  50. data/libxlsxwriter/cocoapods/libxlsxwriter-umbrella.h +2 -1
  51. data/libxlsxwriter/cocoapods/libxlsxwriter.modulemap +2 -2
  52. data/libxlsxwriter/include/xlsxwriter.h +2 -2
  53. data/libxlsxwriter/include/xlsxwriter/app.h +2 -2
  54. data/libxlsxwriter/include/xlsxwriter/chart.h +164 -13
  55. data/libxlsxwriter/include/xlsxwriter/chartsheet.h +544 -0
  56. data/libxlsxwriter/include/xlsxwriter/common.h +35 -6
  57. data/libxlsxwriter/include/xlsxwriter/content_types.h +5 -2
  58. data/libxlsxwriter/include/xlsxwriter/core.h +2 -2
  59. data/libxlsxwriter/include/xlsxwriter/custom.h +2 -2
  60. data/libxlsxwriter/include/xlsxwriter/drawing.h +3 -2
  61. data/libxlsxwriter/include/xlsxwriter/format.h +8 -8
  62. data/libxlsxwriter/include/xlsxwriter/hash_table.h +1 -1
  63. data/libxlsxwriter/include/xlsxwriter/packager.h +18 -8
  64. data/libxlsxwriter/include/xlsxwriter/relationships.h +2 -2
  65. data/libxlsxwriter/include/xlsxwriter/shared_strings.h +5 -3
  66. data/libxlsxwriter/include/xlsxwriter/styles.h +10 -5
  67. data/libxlsxwriter/include/xlsxwriter/theme.h +2 -2
  68. data/libxlsxwriter/include/xlsxwriter/utility.h +35 -5
  69. data/libxlsxwriter/include/xlsxwriter/workbook.h +234 -57
  70. data/libxlsxwriter/include/xlsxwriter/worksheet.h +780 -91
  71. data/libxlsxwriter/include/xlsxwriter/xmlwriter.h +4 -2
  72. data/libxlsxwriter/libxlsxwriter.podspec +4 -2
  73. data/libxlsxwriter/src/Makefile +31 -6
  74. data/libxlsxwriter/src/app.c +2 -2
  75. data/libxlsxwriter/src/chart.c +116 -23
  76. data/libxlsxwriter/src/chartsheet.c +508 -0
  77. data/libxlsxwriter/src/content_types.c +12 -4
  78. data/libxlsxwriter/src/core.c +11 -11
  79. data/libxlsxwriter/src/custom.c +3 -3
  80. data/libxlsxwriter/src/drawing.c +114 -17
  81. data/libxlsxwriter/src/format.c +5 -5
  82. data/libxlsxwriter/src/hash_table.c +1 -1
  83. data/libxlsxwriter/src/packager.c +378 -61
  84. data/libxlsxwriter/src/relationships.c +2 -2
  85. data/libxlsxwriter/src/shared_strings.c +18 -4
  86. data/libxlsxwriter/src/styles.c +59 -12
  87. data/libxlsxwriter/src/theme.c +2 -2
  88. data/libxlsxwriter/src/utility.c +93 -6
  89. data/libxlsxwriter/src/workbook.c +379 -61
  90. data/libxlsxwriter/src/worksheet.c +1240 -174
  91. data/libxlsxwriter/src/xmlwriter.c +18 -9
  92. data/libxlsxwriter/third_party/minizip/Makefile +6 -1
  93. data/libxlsxwriter/third_party/minizip/ioapi.c +10 -0
  94. data/libxlsxwriter/third_party/minizip/zip.c +2 -0
  95. data/libxlsxwriter/third_party/tmpfileplus/tmpfileplus.c +2 -2
  96. data/libxlsxwriter/version.txt +1 -1
  97. data/test/auto_width_test.rb +19 -0
  98. data/test/date_test.rb +34 -0
  99. data/test/format_test.rb +179 -0
  100. data/test/reopen_test.rb +22 -0
  101. data/test/test_helper.rb +23 -4
  102. data/test/text_width_test.rb +80 -0
  103. data/test/tmpfile_test.rb +1 -0
  104. data/test/validations_test.rb +47 -0
  105. data/test/worksheet_test.rb +129 -0
  106. metadata +34 -5
data/Rakefile CHANGED
@@ -16,3 +16,19 @@ Rake::TestTask.new do |test|
16
16
  end
17
17
 
18
18
  #task :default => :test
19
+
20
+ desc "Run all examples"
21
+ task :examples do
22
+ Dir.glob('examples/**/*.rb').each do |file|
23
+ require './' + file.sub(/\.rb$/, '')
24
+ end
25
+ end
26
+
27
+ desc "Compile libxlsxwriter shared library"
28
+ task :compile do
29
+ %x{
30
+ cd ext/fast_excel
31
+ ruby ./extconf.rb
32
+ make
33
+ }
34
+ end
@@ -0,0 +1,25 @@
1
+ install:
2
+ - SET PATH=C:\Ruby%ruby_version%\bin;%PATH%
3
+ - SET PATH=C:\MinGW\bin;%PATH%
4
+ - SET RAKEOPT=-rdevkit
5
+ - copy c:\MinGW\bin\mingw32-make.exe c:\MinGW\bin\make.exe
6
+ - ruby --version
7
+ - gem --version
8
+ - bundle install
9
+ - make
10
+
11
+ build: off
12
+
13
+ test_script:
14
+ - bundle exec rake test
15
+
16
+ environment:
17
+ matrix:
18
+ - ruby_version: "24"
19
+ - ruby_version: "24-x64"
20
+ - ruby_version: "23"
21
+ - ruby_version: "23-x64"
22
+ - ruby_version: "22"
23
+ - ruby_version: "22-x64"
24
+ - ruby_version: "21"
25
+ - ruby_version: "21-x64"
@@ -1,6 +1,6 @@
1
1
  require_relative 'init'
2
2
 
3
- HEADERS = ["id", "name", "age", "date"]
3
+ HEADERS = ["id", "name", "age", "date"].freeze
4
4
 
5
5
  DATA = []
6
6
  1000.times do |n|
@@ -8,15 +8,15 @@ DATA = []
8
8
  end
9
9
 
10
10
  Benchmark.ips do |x|
11
- x.config(time: 10, warmup: 2)
11
+ x.config(time: 10, warmup: 40)
12
12
 
13
13
  x.report("FastExcel") do
14
14
  workbook = FastExcel.open(constant_memory: true)
15
15
  worksheet = workbook.add_worksheet("benchmark")
16
16
 
17
17
  worksheet.write_row(0, HEADERS)
18
- DATA.each_with_index do |row, i|
19
- worksheet.write_row(i + 1, row)
18
+ DATA.each do |row|
19
+ worksheet.append_row(row)
20
20
  end
21
21
  workbook.read_string
22
22
  end
@@ -55,5 +55,18 @@ Benchmark.ips do |x|
55
55
  File.delete(filename)
56
56
  end
57
57
 
58
+ x.report("xlsxtream") do
59
+ filename = "#{Dir.mktmpdir}/xlsxtream.xlsx"
60
+
61
+ Xlsxtream::Workbook.open(filename) do |xlsx|
62
+ xlsx.write_worksheet do |sheet|
63
+ sheet << HEADERS
64
+ DATA.each do |row|
65
+ sheet << row
66
+ end
67
+ end
68
+ end
69
+ end
70
+
58
71
  x.compare!
59
72
  end
@@ -22,5 +22,9 @@ Benchmark.ips do |x|
22
22
  write_xlsx_20k
23
23
  end
24
24
 
25
+ x.report("xlsxtream") do
26
+ write_xlsxtream_20k
27
+ end
28
+
25
29
  x.compare!
26
30
  end
@@ -0,0 +1,37 @@
1
+ require_relative 'init'
2
+
3
+ HEADERS = ["id", "name", "age", "date"]
4
+
5
+ DATA = []
6
+ 1000.times do |n|
7
+ DATA << [n, "String string #{n}", (n * rand * 10).round, Time.at(n * 1000 + 1492922688)]
8
+ end
9
+
10
+ Benchmark.ips do |x|
11
+ x.config(time: 10, warmup: 2)
12
+
13
+ x.report("Normal") do
14
+ workbook = FastExcel.open(constant_memory: true)
15
+ worksheet = workbook.add_worksheet("benchmark")
16
+
17
+ worksheet.write_row(0, HEADERS)
18
+ DATA.each_with_index do |row, i|
19
+ worksheet.write_row(i + 1, row)
20
+ end
21
+ workbook.read_string
22
+ end
23
+
24
+ x.report("With auto_width") do
25
+ workbook = FastExcel.open(constant_memory: true)
26
+ worksheet = workbook.add_worksheet("benchmark")
27
+ worksheet.auto_width = true
28
+
29
+ worksheet.write_row(0, HEADERS)
30
+ DATA.each_with_index do |row, i|
31
+ worksheet.write_row(i + 1, row)
32
+ end
33
+ workbook.read_string
34
+ end
35
+
36
+ x.compare!
37
+ end
@@ -8,10 +8,9 @@ require_relative '../lib/fast_excel'
8
8
  require "benchmark/ips"
9
9
  require 'axlsx'
10
10
  require 'write_xlsx'
11
+ require 'xlsxtream'
11
12
  require 'process_memory'
12
13
 
13
- require_relative 'init'
14
-
15
14
  def write_fast_excel_20k
16
15
  workbook = FastExcel.open(constant_memory: true)
17
16
  worksheet = workbook.add_worksheet("benchmark")
@@ -57,3 +56,16 @@ def write_axlsx_20k
57
56
  File.delete(filename)
58
57
  end
59
58
  end
59
+
60
+ def write_xlsxtream_20k
61
+ filename = "#{Dir.mktmpdir}/xlsxtream.xlsx"
62
+
63
+ Xlsxtream::Workbook.open(filename) do |xlsx|
64
+ xlsx.write_worksheet do |sheet|
65
+ sheet << HEADERS
66
+ DATA.each do |row|
67
+ sheet << row
68
+ end
69
+ end
70
+ end
71
+ end
@@ -11,6 +11,7 @@ puts "warm up..."
11
11
  write_fast_excel_20k
12
12
  write_axlsx_20k
13
13
  write_xlsx_20k
14
+ write_xlsxtream_20k
14
15
 
15
16
  DATA.clear
16
17
  50_000.times do |n|
@@ -47,3 +48,10 @@ sleep 5
47
48
  measure_memory("write_xlsx") do
48
49
  write_xlsx_20k
49
50
  end
51
+
52
+ GC.start
53
+ sleep 5
54
+
55
+ measure_memory("xlsxtream") do
56
+ write_xlsxtream_20k
57
+ end
@@ -0,0 +1,27 @@
1
+ require_relative '../lib/fast_excel'
2
+ require 'ruby-prof'
3
+
4
+ DATA = []
5
+ 1000.times do |n|
6
+ DATA << [n, "String string #{n}", (n * rand * 10).round, Time.at(n * 1000 + 1492922688)]
7
+ end
8
+
9
+ RubyProf.start
10
+
11
+ 100.times do
12
+ workbook = FastExcel.open(constant_memory: true)
13
+ worksheet = workbook.add_worksheet("benchmark")
14
+ worksheet.auto_width = true
15
+
16
+ DATA.each_with_index do |row, i|
17
+ worksheet.write_row(i + 1, row)
18
+ end
19
+ workbook.read_string
20
+
21
+ print '.'
22
+ end
23
+ result = RubyProf.stop
24
+
25
+ # print a flat profile to text
26
+ printer = RubyProf::FlatPrinter.new(result)
27
+ printer.print(STDOUT)
@@ -0,0 +1,62 @@
1
+ require_relative '../lib/fast_excel'
2
+ require "benchmark/memory"
3
+ require "benchmark/ips"
4
+
5
+ DATA = []
6
+ 1000.times do |n|
7
+ DATA << [n, "String string #{n}", (n * rand * 10).round, Time.at(n * 1000 + 1492922688)]
8
+ end
9
+
10
+ 5.times do
11
+ workbook = FastExcel.open(constant_memory: true)
12
+ worksheet = workbook.add_worksheet("benchmark")
13
+
14
+ DATA.each_with_index do |row, row_num|
15
+ row.each_with_index do |val, cell_num|
16
+ worksheet.write_value(row_num + 1, cell_num + 1, val)
17
+ end
18
+ end
19
+ workbook.read_string
20
+ end
21
+
22
+
23
+ workbook = FastExcel.open(constant_memory: true)
24
+ worksheet = workbook.add_worksheet("benchmark")
25
+
26
+ DATA.each_with_index do |row, row_num|
27
+ row.each_with_index do |val, cell_num|
28
+ worksheet.write_value(row_num + 1, cell_num + 1, val)
29
+ end
30
+ end
31
+ workbook.read_string
32
+
33
+ Benchmark.ips do |x|
34
+ #x.config(time: 10, warmup: 2)
35
+
36
+ x.report("Normal") do
37
+ workbook = FastExcel.open(constant_memory: true)
38
+ worksheet = workbook.add_worksheet("benchmark")
39
+
40
+ DATA.each_with_index do |row, row_num|
41
+ row.each_with_index do |val, cell_num|
42
+ worksheet.write_value(row_num + 1, cell_num + 1, val)
43
+ end
44
+ end
45
+ workbook.read_string
46
+ end
47
+
48
+ x.report("Auto-width") do
49
+ workbook = FastExcel.open(constant_memory: true)
50
+ worksheet = workbook.add_worksheet("benchmark")
51
+ worksheet.auto_width = true
52
+
53
+ DATA.each_with_index do |row, row_num|
54
+ row.each_with_index do |val, cell_num|
55
+ worksheet.write_value(row_num + 1, cell_num + 1, val)
56
+ end
57
+ end
58
+ workbook.read_string
59
+ end
60
+
61
+ x.compare!
62
+ end
@@ -1,5 +1,4 @@
1
1
  require_relative '../lib/fast_excel'
2
- require 'pp'
3
2
 
4
3
  workbook = FastExcel.open("example.xlsx", constant_memory: true)
5
4
 
@@ -12,7 +11,7 @@ workbook.default_format.set(
12
11
 
13
12
  worksheet = workbook.add_worksheet("Payments Report")
14
13
 
15
- bold = workbook.bold_cell_format
14
+ bold = workbook.bold_format
16
15
  worksheet.set_column(0, 0, FastExcel::DEF_COL_WIDTH, bold)
17
16
 
18
17
  price = workbook.number_format("#,##0.00")
@@ -21,10 +20,10 @@ worksheet.set_column(1, 1, 20, price)
21
20
  date_format = workbook.number_format("[$-409]m/d/yy h:mm AM/PM;@")
22
21
  worksheet.set_column(2, 2, 20, date_format)
23
22
 
24
- worksheet.write_row(0, ["message", "price", "date"], bold)
23
+ worksheet.write_row(0, ["message", "price", "date", "complete"], bold)
25
24
 
26
25
  for i in 1..1000
27
- worksheet.write_row(i, ["Hello", (rand * 10_000_000).round(2), Time.now])
26
+ worksheet.write_row(i, ["Hello", (rand * 10_000_000).round(2), Time.now, i % 2 == 0])
28
27
 
29
28
  # Or manually
30
29
  # worksheet.write_string(i, 0, "Hello", nil)
@@ -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,26 @@
1
+ require_relative '../lib/fast_excel'
2
+
3
+ workbook = FastExcel.open("example_auto_width.xlsx", constant_memory: false)
4
+
5
+ # this is required to make auto-width works correctly
6
+ workbook.default_format.set(
7
+ font_size: 13,
8
+ font_family: "Arial"
9
+ )
10
+
11
+ worksheet = workbook.add_worksheet
12
+ worksheet.auto_width = true
13
+
14
+ ['Arial', 'Calibri', 'Times New Roman'].each_with_index do |font, index|
15
+ col_format = workbook.add_format(font_family: font, font_size: 17)
16
+ worksheet.set_column(index * 4, index * 4 + 3, 10, col_format)
17
+
18
+ worksheet.write_value(0, index * 4 + 2, font)
19
+ worksheet.write_value(1, index * 4, "tini")
20
+ worksheet.write_value(1, index * 4 + 1, "Longer")
21
+ worksheet.write_value(1, index * 4 + 2, "Some longer text!")
22
+ worksheet.write_value(1, index * 4 + 3, "This gem is FFI binding for libxlsxwriter C library")
23
+ end
24
+
25
+ workbook.close
26
+ puts "Saved to file example_auto_width.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,36 @@
1
+ require_relative '../lib/fast_excel'
2
+
3
+ `rm example_filters.xlsx` if File.exist?('example_filters.xlsx')
4
+ workbook = FastExcel.open("example_filters.xlsx", constant_memory: false)
5
+
6
+ workbook.default_format.set(
7
+ font_size: 0, # user's default
8
+ #font_family: "Arial"
9
+ )
10
+
11
+ # pp workbook.default_format
12
+
13
+ worksheet = workbook.add_worksheet("Payments Report")
14
+
15
+ p worksheet[:filter_on]
16
+ FastExcel.print_ffi_obj(worksheet)
17
+
18
+ bold = workbook.bold_format
19
+ worksheet.set_column(0, 0, FastExcel::DEF_COL_WIDTH, bold)
20
+
21
+ price = workbook.number_format("#,##0.00")
22
+ worksheet.set_column(1, 1, 20, price)
23
+
24
+ date_format = workbook.number_format("[$-409]m/d/yy h:mm AM/PM;@")
25
+ worksheet.set_column(2, 2, 20, date_format)
26
+
27
+ worksheet.write_row(0, ["message", "price", "date", "complete"], bold)
28
+
29
+ for i in 1..1000
30
+ worksheet.write_row(i, ["Hello", (rand * 10_000_000).round(2), Time.now, i % 2 == 0])
31
+ end
32
+
33
+ worksheet.enable_filters!(end_col: 3)
34
+
35
+ workbook.close
36
+ puts "Saved to file example_filters.xlsx"
@@ -1,6 +1,4 @@
1
1
  require_relative '../lib/fast_excel'
2
- require 'pp'
3
- require 'looksee'
4
2
 
5
3
  workbook = FastExcel.open("example_formula.xlsx", constant_memory: false)
6
4
 
@@ -12,9 +10,7 @@ worksheet.write_row(2, ["Phone", 0.138])
12
10
  worksheet.write_row(3, ["Mouse", 0.099])
13
11
  worksheet.write_row(4, ["Speaker", 2.5])
14
12
  worksheet.write_row(5, ["Camera", 0.383])
15
- worksheet.write_row(6, ["Total", FastExcel::Formula.new("SUM(B2:B6)")], workbook.bold_cell_format)
16
-
17
- bold = workbook.bold_cell_format
13
+ worksheet.write_row(6, ["Total", FastExcel::Formula.new("SUM(B2:B6)")], workbook.bold_format)
18
14
 
19
15
  workbook.close
20
16
  puts "Saved to file example_formula.xlsx"