fast_excel 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
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