fast_excel 0.2.1 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ac39efd3391a98291ae2c1f5ba4102850b8ad678
4
- data.tar.gz: 7d2eb11896d20f80f20405778b009e09ac1b41ea
3
+ metadata.gz: f0bf8afa4f1566ae7cc27fe6b7a59e1d9c0dc0d0
4
+ data.tar.gz: eeac6d37268bfc90e54a338e098224acd382309d
5
5
  SHA512:
6
- metadata.gz: ae26296476e89298ff1d584ae59e87e81f46a118e0c7583f5328fb12845afe970e1fe040c8783388e541d3b4077948957cec5923cd124d325475629e5272c495
7
- data.tar.gz: 921ca060bf7cb21c541dc0664767a13d5f95be2f76d7947c24e2677133c06cc21d558f925e372b4d49f4fc56977650a13c876883e3b0f3850ba2f4953ab565a5
6
+ metadata.gz: 75345de42e34f5e4db76737ba2c1ad8d8c2fa74fb44653d1d0c5a86137d635aab3c2abb5297ad32fe6a67e4813e6c57dbd50c543ea5a75404a44ada017e45c2b
7
+ data.tar.gz: c37550f5d67c501b16e9199f0a8aab489ea760257d2405f3b0ffbabcb41e20625ee80dfbb89bc7dec1ddb0bf93cc65c5e59b89de55f1727dbb5d85ead3a1e049
data/.travis.yml ADDED
@@ -0,0 +1,28 @@
1
+ ---
2
+ language: ruby
3
+
4
+ matrix:
5
+ include:
6
+ - os: linux
7
+ rvm: 2.1
8
+ - os: osx
9
+ rvm: 2.1
10
+ - os: linux
11
+ rvm: 2.2.7
12
+ - os: osx
13
+ rvm: 2.2.7
14
+ - os: linux
15
+ rvm: 2.3.4
16
+ - os: osx
17
+ rvm: 2.3.4
18
+ - os: linux
19
+ rvm: 2.4.0
20
+ - os: osx
21
+ rvm: 2.4.0
22
+ fast_finish: true
23
+
24
+ script:
25
+ - bundle install
26
+ - make
27
+ - bundle exec rake test
28
+ - bundle exec rake examples
data/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ #### Version 0.2.2 - 20 sep 2017
2
+
3
+ * Nice setters and getters for format.align
4
+ * Add nice setters for colors and borders
5
+ * Add sheet.append_row, sheet.last_row_number
6
+ * Run tests in CI
7
+ * Performance optimizations and type check refactoring
8
+ * Add styles_example.rb
9
+ * Fix assigning align from other format
10
+
1
11
  #### Version 0.2.1 - 20 jun 2017
2
12
 
3
13
  * Add FastExcel::Formula
data/Gemfile CHANGED
@@ -3,6 +3,8 @@ source 'https://rubygems.org'
3
3
  gem 'ffi'
4
4
  gem 'ffi_gen', require: false
5
5
 
6
+ gem 'rake'
7
+
6
8
  gem 'roo', '2.7.1', git: 'https://github.com/roo-rb/roo.git'
7
9
 
8
10
  gem 'minitest'
@@ -12,4 +14,4 @@ gem 'minitest-reporters'
12
14
  gem 'axlsx', git: 'https://github.com/randym/axlsx.git'
13
15
  gem 'write_xlsx'
14
16
  gem 'benchmark-ips'
15
- gem 'process_memory', git: 'https://github.com/paxa/process_memory'
17
+ gem 'process_memory', git: 'https://github.com/paxa/process_memory', platforms: :ruby
data/Gemfile.lock CHANGED
@@ -16,7 +16,7 @@ GIT
16
16
 
17
17
  GIT
18
18
  remote: https://github.com/roo-rb/roo.git
19
- revision: 6bde8588dfd97d7a18981ee3ac7b444fec165a2c
19
+ revision: 85c2736b0ea1c984391688c5aeb4acf85f225405
20
20
  specs:
21
21
  roo (2.7.1)
22
22
  nokogiri (~> 1)
@@ -33,18 +33,19 @@ GEM
33
33
  ffi (~> 1.0)
34
34
  htmlentities (4.3.4)
35
35
  mimemagic (0.3.2)
36
- mini_portile2 (2.1.0)
37
- minitest (5.10.1)
36
+ mini_portile2 (2.2.0)
37
+ minitest (5.10.2)
38
38
  minitest-reporters (1.1.14)
39
39
  ansi
40
40
  builder
41
41
  minitest (>= 5.0)
42
42
  ruby-progressbar
43
- nokogiri (1.7.1)
44
- mini_portile2 (~> 2.1.0)
43
+ nokogiri (1.8.0)
44
+ mini_portile2 (~> 2.2.0)
45
+ rake (12.0.0)
45
46
  ruby-progressbar (1.8.1)
46
47
  rubyzip (1.2.1)
47
- write_xlsx (0.83.0)
48
+ write_xlsx (0.85.1)
48
49
  rubyzip (>= 1.0.0)
49
50
  zip-zip
50
51
  zip-zip (0.3)
@@ -61,8 +62,9 @@ DEPENDENCIES
61
62
  minitest
62
63
  minitest-reporters
63
64
  process_memory!
65
+ rake
64
66
  roo (= 2.7.1)!
65
67
  write_xlsx
66
68
 
67
69
  BUNDLED WITH
68
- 1.14.5
70
+ 1.15.1
data/Rakefile CHANGED
@@ -16,3 +16,9 @@ Rake::TestTask.new do |test|
16
16
  end
17
17
 
18
18
  #task :default => :test
19
+
20
+ task :examples do
21
+ Dir.glob('examples/**/*.rb').each do |file|
22
+ require './' + file.sub(/\.rb$/, '')
23
+ end
24
+ end
data/appveyor.yml ADDED
@@ -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"
data/examples/example.rb CHANGED
@@ -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
 
@@ -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,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"
@@ -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
 
@@ -7,7 +7,7 @@ img_options = Libxlsxwriter::ImageOptions.new
7
7
  img_options[:x_offset] = 0
8
8
  img_options[:y_offset] = 0
9
9
 
10
- worksheet.insert_image_opt(3, 3, "libxlsxwriter/examples/logo.png", img_options)
10
+ worksheet.insert_image_opt(3, 3, "examples/logo.png", img_options)
11
11
 
12
12
  workbook.close
13
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/fast_excel.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "fast_excel"
3
- s.version = "0.2.1"
3
+ s.version = "0.2.2"
4
4
  s.author = ["Pavel Evstigneev"]
5
5
  s.email = ["pavel.evst@gmail.com"]
6
6
  s.homepage = "https://github.com/paxa/fast_excel"
data/lib/fast_excel.rb CHANGED
@@ -110,15 +110,197 @@ module FastExcel
110
110
  nil
111
111
  end
112
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
+
113
291
  module AttributeHelper
114
292
  def set(values)
115
293
  values.each do |key, value|
116
294
  if respond_to?("#{key}=")
117
295
  send("#{key}=", value)
296
+ elsif respond_to?("set_#{key}=")
297
+ send("set_#{key}=", value)
118
298
  else
119
299
  self[key] = value
120
300
  end
121
301
  end
302
+
303
+ self
122
304
  end
123
305
 
124
306
  def fields_hash
@@ -144,6 +326,12 @@ module FastExcel
144
326
  super(struct)
145
327
  end
146
328
 
329
+ def add_format(options = nil)
330
+ new_format = super()
331
+ new_format.set(options) if options
332
+ new_format
333
+ end
334
+
147
335
  def bold_cell_format
148
336
  bold = add_format
149
337
  bold.set_bold
@@ -159,7 +347,9 @@ module FastExcel
159
347
  end
160
348
 
161
349
  def add_worksheet(sheetname = nil)
162
- super
350
+ sheet = super
351
+ sheet.workbook = self
352
+ sheet
163
353
  end
164
354
 
165
355
  def close
@@ -177,9 +367,16 @@ module FastExcel
177
367
  def remove_tmp_file
178
368
  File.delete(filename) if tmp_file
179
369
  end
370
+
371
+ def constant_memory?
372
+ #FastExcel.print_ffi_obj(self[:options])
373
+ @constant_memory ||= self[:options][:constant_memory] != 0
374
+ end
180
375
  end
181
376
 
182
377
  module WorksheetExt
378
+ attr_accessor :workbook
379
+
183
380
  include AttributeHelper
184
381
 
185
382
  def write_row(row_number, values, formats = nil)
@@ -188,28 +385,62 @@ module FastExcel
188
385
  formats.is_a?(Array) ? formats[index] : formats
189
386
  end
190
387
 
191
- if value.is_a?(Integer) || value.is_a?(Numeric) || value.is_a?(Float)
192
- write_number(row_number, index, value, format)
193
- elsif defined?(BigDecimal) && value.is_a?(BigDecimal)
194
- write_number(row_number, index, value.to_f, format)
195
- elsif defined?(DateTime) && value.is_a?(DateTime)
196
- write_datetime(row_number, index, FastExcel.lxw_datetime(value), format)
197
- elsif value.is_a?(Time)
198
- write_datetime(row_number, index, FastExcel.lxw_time(value), format)
199
- elsif value.is_a?(Formula)
200
- write_formula(row_number, index, value.fml, format)
201
- else
202
- write_string(row_number, index, value.to_s, format)
203
- end
388
+ write_value(row_number, index, value, format)
204
389
  end
205
390
  end
206
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
+
207
438
  end
208
439
 
209
440
  module FormatExt
210
441
  include AttributeHelper
211
442
 
212
- [:font_size, :underline, :font_script, :align, :rotation, :indent, :pattern, :border].each do |prop|
443
+ [:font_size, :underline, :font_script, :rotation, :indent, :pattern, :border].each do |prop|
213
444
  define_method(prop) do
214
445
  self[prop]
215
446
  end
@@ -237,73 +468,121 @@ module FastExcel
237
468
  end
238
469
  end
239
470
 
240
- def set_font_size(value)
241
- if value < 0
242
- raise ArgumentError, "font size should be >= 0 (use 0 for user default font size)"
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"
243
518
  end
244
- super(value)
245
519
  end
246
520
 
247
- def font_family
248
- font_name
521
+ def align
522
+ {
523
+ horizontal: ALIGN_ENUM.find(self[:text_h_align]),
524
+ vertical: ALIGN_ENUM.find(self[:text_v_align])
525
+ }
249
526
  end
250
527
 
251
- def font_family=(value)
252
- self.font_name = value
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
253
535
  end
254
- end
255
536
 
256
- module RowExt
257
- include AttributeHelper
258
-
259
- def inspect
260
- attr_str = fields_hash.map do |key, val|
261
- "@#{key}=#{val.inspect}"
262
- end
263
- "<Libxlsxwriter::Row #{attr_str.join(" ")}>"
537
+ [:bottom_color, :left_color, :right_color, :top_color].each do |prop|
538
+ alias_method :"border_#{prop}=", :"#{prop}="
539
+ alias_method :"border_#{prop}", :"#{prop}"
264
540
  end
265
- end
266
541
 
267
- module CellExt
268
- include AttributeHelper
542
+ BORDER_ENUM = Libxlsxwriter.enum_type(:format_borders)
269
543
 
270
- def value
271
- if self[:type] == :number_cell
272
- self[:u][:number]
273
- elsif self[:type] == :string_cell
274
- pointer = self[:u][:string]
275
- p pointer
276
- pointer.null? ? nil : pointer.to_ptr.read_string
277
- else
278
- self[:user_data1]
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])
279
551
  end
280
- end
281
552
 
282
- def user_data1
283
- value
284
- #self[:user_data1] && !self[:user_data1].null? ? self[:user_data1].to_ptr.read_string : nil
553
+ unless prop == :diag_border
554
+ alias_method :"border_#{prop}=", :"#{prop}="
555
+ alias_method :"border_#{prop}", :"#{prop}"
556
+ end
285
557
  end
286
558
 
287
- def user_data2
288
- self[:user_data2] #&& !self[:user_data2].null? ? self[:user_data2].to_ptr.read_string : nil
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}"
289
571
  end
290
572
 
291
- def sst_string
292
- self[:sst_string] #&& !self[:sst_string].null? ? self[:sst_string].to_ptr.read_string : nil
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)
293
578
  end
294
579
 
295
- #def inspect
296
- # attr_str = fields_hash.map do |key, val|
297
- # "@#{key}=#{val.inspect}"
298
- # end
299
- # "<Libxlsxwriter::Row #{attr_str.join(" ")}>"
300
- #end
580
+ def font_family
581
+ font_name
582
+ end
301
583
 
302
- def inspect
303
- attr_str = fields_hash.map do |key, val|
304
- "@#{key}=#{val.inspect}"
305
- end
306
- "<Libxlsxwriter::Row #{attr_str.join(" ")}>"
584
+ def font_family=(value)
585
+ self.font_name = value
307
586
  end
308
587
  end
309
588
  end
@@ -319,11 +598,3 @@ end
319
598
  Libxlsxwriter::Worksheet.instance_eval do
320
599
  include FastExcel::WorksheetExt
321
600
  end
322
-
323
- Libxlsxwriter::Row.instance_eval do
324
- include FastExcel::RowExt
325
- end
326
-
327
- Libxlsxwriter::Cell.instance_eval do
328
- include FastExcel::CellExt
329
- end
@@ -0,0 +1,171 @@
1
+ require_relative 'test_helper'
2
+
3
+ describe "FastExcel::FormatExt align" do
4
+
5
+ before do
6
+ @workbook = FastExcel.open(constant_memory: true)
7
+ @format = @workbook.add_format
8
+ end
9
+
10
+ it "should give default aligns" do
11
+ assert_equal({horizontal: :align_none, vertical: :align_none}, @format.align)
12
+ end
13
+
14
+ it "should set align by full name" do
15
+ @format.align = :align_center
16
+ assert_equal({horizontal: :align_center, vertical: :align_none}, @format.align)
17
+ end
18
+
19
+ it "should set by string" do
20
+ @format.align = "align_center"
21
+ assert_equal({horizontal: :align_center, vertical: :align_none}, @format.align)
22
+ end
23
+
24
+ it "should set by short name" do
25
+ @format.align = :center
26
+ assert_equal({horizontal: :align_center, vertical: :align_none}, @format.align)
27
+ end
28
+
29
+ it "should set by hash" do
30
+ @format.align = {v: "center", h: "center"}
31
+ assert_equal({horizontal: :align_center, vertical: :align_vertical_center}, @format.align)
32
+ end
33
+
34
+ it "should raise exception for unknown value" do
35
+ error = assert_raises(ArgumentError) do
36
+ @format.align = :aaa
37
+ end
38
+
39
+ assert_equal(error.message, "Can not set align = :aaa, possible values are: [:align_none, :align_left, "\
40
+ ":align_center, :align_right, :align_fill, :align_justify, :align_center_across, :align_distributed, "\
41
+ ":align_vertical_top, :align_vertical_bottom, :align_vertical_center, :align_vertical_justify, :align_vertical_distributed]")
42
+ end
43
+
44
+ it "should raise exception for unknown hash key" do
45
+ error = assert_raises(ArgumentError) do
46
+ @format.align = {aaa: 1}
47
+ end
48
+
49
+ assert_equal(error.message, "Not allowed keys for align: [:aaa], possible keys: [:horizontal, :h, :vertical, :v]")
50
+ end
51
+
52
+ it "should get and set" do
53
+ @format.align = {h: :center, v: :center}
54
+ format2 = @workbook.add_format(align: @format.align)
55
+
56
+ assert_equal({horizontal: :align_center, vertical: :align_vertical_center}, format2.align)
57
+ end
58
+
59
+ end
60
+
61
+
62
+ describe "FastExcel::FormatExt colors" do
63
+
64
+ before do
65
+ workbook = FastExcel.open(constant_memory: true)
66
+ @format = workbook.add_format
67
+ end
68
+
69
+ it "should set font color as hex num" do
70
+ @format.font_color = 0xFF0000
71
+ assert_equal(0xFF0000, @format.font_color)
72
+ end
73
+
74
+ it "should set font color as hex string" do
75
+ @format.font_color = '0xFF0000'
76
+ assert_equal(0xFF0000, @format.font_color)
77
+ end
78
+
79
+ it "should set font color as css hex string" do
80
+ @format.font_color = '#FF0000'
81
+ assert_equal(0xFF0000, @format.font_color)
82
+ end
83
+
84
+ it "should set font color as short hex string" do
85
+ @format.font_color = 'FF0000'
86
+ assert_equal(0xFF0000, @format.font_color)
87
+ end
88
+
89
+ it "should set font color as name" do
90
+ @format.font_color = 'red'
91
+ assert_equal(0xFF0000, @format.font_color)
92
+ end
93
+
94
+ it "should set font css color" do
95
+ @format.font_color = 'alice_blue'
96
+ assert_equal(0xF0F8FF, @format.font_color)
97
+ end
98
+
99
+ it "should allow to use symbol" do
100
+ @format.font_color = :alice_blue
101
+ assert_equal(0xF0F8FF, @format.font_color)
102
+ end
103
+
104
+ it "should have long method for border colors" do
105
+ @format.border_bottom_color = :alice_blue
106
+ assert_equal(0xF0F8FF, @format.border_bottom_color)
107
+ assert_equal(0xF0F8FF, @format.bottom_color)
108
+ end
109
+
110
+ it "should raise for unexpected type" do
111
+ error = assert_raises(ArgumentError) do
112
+ @format.font_color = {aaa: 1}
113
+ end
114
+
115
+ assert_equal(error.message, "Can not use Hash ({:aaa=>1}) for color value, expected String or Hex Number")
116
+ end
117
+
118
+ it "should raise for unexpected color" do
119
+ error = assert_raises(ArgumentError) do
120
+ @format.font_color = :aaa
121
+ end
122
+
123
+ assert_equal(error.message, "Unknown color value :aaa, expected hex string or color name")
124
+ end
125
+
126
+ end
127
+
128
+
129
+ describe "FastExcel::FormatExt border" do
130
+
131
+ before do
132
+ workbook = FastExcel.open(constant_memory: true)
133
+ @format = workbook.add_format
134
+ end
135
+
136
+ it "should set border as symbol" do
137
+ @format.bottom = :border_thin
138
+ assert_equal(:border_thin, @format.bottom)
139
+ end
140
+
141
+ it "should set border as short symbol" do
142
+ @format.bottom = :thin
143
+ assert_equal(:border_thin, @format.bottom)
144
+ end
145
+
146
+ it "should set border as string" do
147
+ @format.bottom = "thin"
148
+ assert_equal(:border_thin, @format.bottom)
149
+ end
150
+
151
+ it "should set border as number" do
152
+ @format.bottom = 1
153
+ assert_equal(:border_thin, @format.bottom)
154
+ end
155
+
156
+ it "should set border with long prop name" do
157
+ error = assert_raises(ArgumentError) do
158
+ @format.border_bottom = :aaa
159
+ end
160
+
161
+ assert_equal(error.message, "Unknown value :aaa for border. Possible values: "\
162
+ "[:none, :thin, :medium, :dashed, :dotted, :thick, :double, :hair, :medium_dashed, "\
163
+ ":dash_dot, :medium_dash_dot, :dash_dot_dot, :medium_dash_dot_dot, :slant_dash_dot]")
164
+ end
165
+
166
+ it "should get value with long name" do
167
+ @format.bottom = "thin"
168
+ assert_equal(:border_thin, @format.border_bottom)
169
+ end
170
+
171
+ end
data/test/test_helper.rb CHANGED
@@ -20,9 +20,13 @@ ensure
20
20
  File.delete(file_path)
21
21
  end
22
22
 
23
+ def get_arrays(workbook)
24
+ workbook.close
25
+ parse_xlsx_as_matrix(workbook.filename)
26
+ end
27
+
23
28
  def parse_xlsx_as_array(file_path)
24
- excel = parse_xlsx(file_path)
25
- data = excel.to_matrix.to_a
29
+ data = parse_xlsx_as_matrix(file_path)
26
30
  headers = data.shift
27
31
 
28
32
  data.map do |row|
@@ -32,5 +36,17 @@ end
32
36
 
33
37
  def parse_xlsx_as_matrix(file_path)
34
38
  excel = parse_xlsx(file_path)
35
- excel.to_matrix.to_a
36
- end
39
+
40
+ sheet = excel.sheet(0)
41
+
42
+ rows = []
43
+ 1.upto(sheet.last_row) do |row_number|
44
+ row = 1.upto(sheet.last_column).map do |col|
45
+ sheet.cell(row_number, col)
46
+ end
47
+
48
+ rows << row
49
+ end
50
+
51
+ return rows
52
+ end
@@ -0,0 +1,86 @@
1
+ require_relative 'test_helper'
2
+
3
+ describe "FastExcel::WorksheetExt append_row" do
4
+
5
+ before do
6
+ @workbook = FastExcel.open(constant_memory: false)
7
+ @worksheet = @workbook.add_worksheet
8
+ end
9
+
10
+ it "should have last_row_number = -1" do
11
+ assert_equal(-1, @worksheet.last_row_number)
12
+ end
13
+
14
+ it "should write_value and update last_row_number" do
15
+ @worksheet.write_value(0, 2, "aaa")
16
+ assert_equal(0, @worksheet.last_row_number)
17
+ assert_equal([[nil, nil, "aaa"]], get_arrays(@workbook))
18
+ end
19
+
20
+ it "should append row and update last_row_number" do
21
+ @worksheet.append_row(["aaa", "bbb", "ccc"])
22
+ @worksheet.append_row(["ddd", "eee", "fff"])
23
+
24
+ assert_equal(1, @worksheet.last_row_number)
25
+ assert_equal([["aaa", "bbb", "ccc"], ["ddd", "eee", "fff"]], get_arrays(@workbook))
26
+ end
27
+
28
+ it "should write_row then append and update last_row_number" do
29
+ @worksheet.write_row(3, ["aaa", "bbb", "ccc"])
30
+ @worksheet.append_row(["ddd", "eee", "fff"])
31
+
32
+ assert_equal(4, @worksheet.last_row_number)
33
+ assert_equal(
34
+ [
35
+ [nil, nil, nil],
36
+ [nil, nil, nil],
37
+ [nil, nil, nil],
38
+ ["aaa", "bbb", "ccc"],
39
+ ["ddd", "eee", "fff"]
40
+ ],
41
+ get_arrays(@workbook)
42
+ )
43
+ end
44
+
45
+ it "should not reduce last_row_number" do
46
+ @worksheet.append_row(["aaa", "bbb", "ccc"])
47
+ @worksheet.append_row(["ddd", "eee", "fff"])
48
+ @worksheet.write_value(0, 4, "foo")
49
+ @worksheet.append_row(["111", "222", "333"])
50
+
51
+ assert_equal(2, @worksheet.last_row_number)
52
+ assert_equal(
53
+ [
54
+ ["aaa", "bbb", "ccc", nil, "foo"],
55
+ ["ddd", "eee", "fff", nil, nil],
56
+ ["111", "222", "333", nil, nil]
57
+ ],
58
+ get_arrays(@workbook)
59
+ )
60
+ end
61
+
62
+ it "should not allow to write rows that already saved" do
63
+ @workbook = FastExcel.open(constant_memory: true)
64
+ @worksheet = @workbook.add_worksheet
65
+
66
+ @worksheet.append_row(["aaa", "bbb", "ccc"])
67
+ @worksheet.append_row(["ddd", "eee", "fff"])
68
+
69
+ error = assert_raises(ArgumentError) do
70
+ @worksheet.write_value(0, 4, "foo")
71
+ end
72
+
73
+ assert_equal("Can not write to saved row in constant_memory mode (attempted row: 0, last saved row: 1)", error.message)
74
+ end
75
+
76
+ it "should write bigdecimal as a number" do
77
+ require 'bigdecimal'
78
+
79
+ @workbook = FastExcel.open(constant_memory: true)
80
+ @worksheet = @workbook.add_worksheet
81
+
82
+ @worksheet.append_row([BigDecimal.new("0.1234")])
83
+
84
+ assert_equal([[0.1234]], get_arrays(@workbook))
85
+ end
86
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fast_excel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pavel Evstigneev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-06-20 00:00:00.000000000 Z
11
+ date: 2017-09-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi
@@ -39,20 +39,26 @@ extensions:
39
39
  extra_rdoc_files: []
40
40
  files:
41
41
  - ".gitignore"
42
+ - ".travis.yml"
42
43
  - CHANGELOG.md
43
44
  - Gemfile
44
45
  - Gemfile.lock
45
46
  - Makefile
46
47
  - README.md
47
48
  - Rakefile
49
+ - appveyor.yml
48
50
  - benchmarks/1k_rows.rb
49
51
  - benchmarks/20k_rows.rb
50
52
  - benchmarks/init.rb
51
53
  - benchmarks/memory.rb
52
54
  - examples/example.rb
55
+ - examples/example_align.rb
53
56
  - examples/example_chart.rb
57
+ - examples/example_colors.rb
54
58
  - examples/example_formula.rb
55
59
  - examples/example_image.rb
60
+ - examples/example_styles.rb
61
+ - examples/logo.png
56
62
  - extconf.rb
57
63
  - fast_excel.gemspec
58
64
  - lib/fast_excel.rb
@@ -145,8 +151,10 @@ files:
145
151
  - libxlsxwriter/version.txt
146
152
  - test/date_test.rb
147
153
  - test/default_format_test.rb
154
+ - test/format_test.rb
148
155
  - test/test_helper.rb
149
156
  - test/tmpfile_test.rb
157
+ - test/worksheet_test.rb
150
158
  homepage: https://github.com/paxa/fast_excel
151
159
  licenses:
152
160
  - MIT