rxl 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +47 -10
  3. data/lib/cell.rb +83 -21
  4. data/lib/rxl/version.rb +1 -1
  5. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6991fc216795b685c75f3bf7b4222520e428a9b021bac623bc7501e817fd6453
4
- data.tar.gz: a99745263d114493fff4802e534f2c97757c7fe75bc6a23726d2a4ad6df7a466
3
+ metadata.gz: 7820fff21fd0ba92fb5904c2a1a72a303c369830df9018ef12594ee5da572f8c
4
+ data.tar.gz: 101f2adf3cd52dc9b25357e772b95cb74121c4f8c66a6effeb7de7ac5de28816
5
5
  SHA512:
6
- metadata.gz: 192009987d16a7b84bd611f62ded016dd230eeb9938eb0e963ba2608ce6414de2821d9669537f340299d1788a67b29cb1c39c3b668b48edb1d09be7af8490086
7
- data.tar.gz: 71d91a553075e6af3cc4e8e8729cf45e10afe647dc1049abcefd11898064d04a810f1e2d8aaa1f183b4dcee1c1c2494fca8b77829cc9e496b5e938c95f28678f
6
+ metadata.gz: 37d51c7a106c7daab8f244726efada37d1e31f178aae7618a1821450898f48e211ce9bf3fa1c7ffdfb25d740a3031b671228922863362f883566c5980ce8d1cd
7
+ data.tar.gz: 71ed2283fe0f700ff366e97912cb35863005527c32966722debae51195f4f5ba59a633acc91cf23dbd15917c3e730b63256507c312a380079f695d1816e27d39
data/README.md CHANGED
@@ -60,7 +60,8 @@ The format of the excel read hash has the following skeleton:
60
60
  Bear in mind the limitations of reading cell formats. Everything is read as a string other than:
61
61
  * cells formatted as dates are converted to a DateTime object with the time portion set to midnight
62
62
  * cells formatted as times are converted to a DateTime object with the date portion set to 31/12/1899 - unless the cell has a date prefix in which case this is carried in (this will be read as a date format as per below parsing rules)
63
- * numbers (including floats and percentages) where the cell format is number or percentage are read in as integers - trailing zeroes are cropped from floats in this case and percentages are converted to numeric format (eg 100% = 1)
63
+ * percentages are converted to numeric format (eg 100% = 1)
64
+ * to account for floats, which lose any trailing zeroes, decimal point information is retained in the `:decimals` value
64
65
  * formulas are not read from cells with date and time formats
65
66
 
66
67
  Within these limitations the cell hash's :format holds the best analysis of the original cell format but as there's no way to extract all of the format information directly from the sheet some information may need to be refurbished as required after import via Rxl.
@@ -152,21 +153,58 @@ The format of the excel hash_workbook has sheet names as keys and hashes of cell
152
153
 
153
154
  #### Cell specification
154
155
 
155
- All cells are written with the format set to general except those with a number format specified
156
+ ##### Output formatting
157
+
158
+ All cells are written with the format set to general by default
159
+
160
+ If the value is a DateTime object then use `:date_format` with a date format as per the below examples, the default is 'dd/mm/yyyy'
161
+
162
+ If `:format` is given as `:percentage` where the value is a number or float then the format defaults to a matching format (eg '0' for 1, '0.0' for 0.1), override using `:number_format` if trailing zeroes are required or rounding is needed
156
163
 
157
164
  Specify the number format according to https://support.office.com/en-us/article/number-format-codes-5026bbd6-04bc-48cd-bf33-80f18b4eae68?ui=en-US&rs=en-US&ad=US
158
165
 
159
166
  Examples:
160
167
 
161
- | value | number format | resulting cell format | resulting cell value |
168
+ | value | number_format | resulting cell format | resulting cell value |
169
+ |--------------|---------------|-----------------------|----------------------|
170
+ | 0 | '0' | number | 0 |
171
+ | 0.49 | '0' | number | 0 |
172
+ | 0.5 | '0' | number | 1 |
173
+ | 0 | '0.00' | number | 0.00 |
174
+ | 0.5 | '0.00' | number | 0.50 |
175
+ | 0 |' 0%' | percentage | 0% |
176
+ | 1 | '0%' | percentage | 100% |
177
+ | 0.101 | '0.00%' | percentage | 10.10% |
178
+ | 1 | '0.00%' | percentage | 100.00% |
179
+
180
+ | value | date_format | resulting cell format | resulting cell value |
162
181
  |--------------|---------------|-----------------------|----------------------|
163
- | 0 | 0 | number | 0 |
164
- | 0.49 | 0 | number | 0 |
165
- | 0.5 | 0 | number | 1 |
166
- | 0 | 0.00 | number | 0.00 |
167
- | 0 | 0% | percentage | 0% |
168
- | 1 | 0% | percentage | 100% |
169
182
  | '01/01/2000' | 'dd/mm/yyyy' | date | 01/01/2000 |
183
+ | '01/01/2000' | 'dd-mmm-yyyy' | date | 01-Jan-2000 |
184
+ | '01:00:00' | 'hh:mm:ss' | time | 01:00:00 |
185
+
186
+ ##### Cell formatting
187
+
188
+ TODO: add more cell formatting
189
+
190
+ ```ruby
191
+ {
192
+ 'A1' => {
193
+ value: 'some_text',
194
+ font_name: 'Arial',
195
+ font_size: 8,
196
+ bold: true,
197
+ h_align: :center,
198
+ v_align: :center,
199
+ fill: 'a1b2c3',
200
+ border: { top: 'thin', bottom: 'thin', left: 'thin', right: 'thin' }
201
+ }
202
+ }
203
+ ```
204
+
205
+ ##### Formulas
206
+
207
+ Formulas are read and written from/to the `:formula` value and on write supercede and value specified, however due to some unknown issue, formulas which were written via this gem can then be re-read but the cell value will be empty
170
208
 
171
209
  #### Write Validation
172
210
 
@@ -180,7 +218,6 @@ The following rules are validated for write_file:
180
218
  * The hash_worksheet values must be hashes (specifying cells)
181
219
  * The hash_cell keys must conform the the cell specification as below
182
220
 
183
- * If a formula is provided the value must be nil or an empty string
184
221
  * If a number format is provided the value must be consistent with it
185
222
 
186
223
 
data/lib/cell.rb CHANGED
@@ -8,20 +8,37 @@ module Cell
8
8
 
9
9
  def self.rubyxl_cell_to_hash_cell(rubyxl_cell = nil)
10
10
  rubyxl_cell_value = rubyxl_cell.nil? ? RubyXL::Cell.new.value : rubyxl_cell.value
11
+ rubyxl_cell_value = resolve_date_ms(rubyxl_cell_value) if rubyxl_cell_value.is_a?(Date)
12
+ format = hash_cell_format(rubyxl_cell_value)
11
13
  {
12
- value: rubyxl_cell_value,
13
- format: hash_cell_format(rubyxl_cell_value),
14
- formula: rubyxl_cell_formula(rubyxl_cell),
15
- h_align: rubyxl_cell_h_align(rubyxl_cell),
16
- v_align: rubyxl_cell_v_align(rubyxl_cell),
17
- bold: rubyxl_cell.nil? ? false : rubyxl_cell.is_bolded,
18
- fill: rubyxl_cell.nil? ? 'ffffff' : rubyxl_cell.fill_color,
19
- font_name: rubyxl_cell.nil? ? 'Calibri' : rubyxl_cell.font_name,
20
- font_size: rubyxl_cell.nil? ? 12 : rubyxl_cell.font_size.to_i,
21
- border: rubyxl_cell_to_border_hash(rubyxl_cell)
14
+ value: rubyxl_cell_value,
15
+ format: format,
16
+ formula: rubyxl_cell_formula(rubyxl_cell),
17
+ decimals: format == :number ? decimals(rubyxl_cell) : nil,
18
+ h_align: rubyxl_cell_h_align(rubyxl_cell),
19
+ v_align: rubyxl_cell_v_align(rubyxl_cell),
20
+ bold: rubyxl_cell.nil? ? false : rubyxl_cell.is_bolded,
21
+ fill: rubyxl_cell.nil? ? 'ffffff' : rubyxl_cell.fill_color,
22
+ font_name: rubyxl_cell.nil? ? 'Calibri' : rubyxl_cell.font_name,
23
+ font_size: rubyxl_cell.nil? ? 12 : rubyxl_cell.font_size.to_i,
24
+ border: rubyxl_cell_to_border_hash(rubyxl_cell)
22
25
  }
23
26
  end
24
27
 
28
+ def self.resolve_date_ms(value)
29
+ value_ut = value.strftime('%s')
30
+ ut = value.strftime('%L').to_i > 499 ? "#{value_ut.to_i + 1}" : value_ut
31
+ DateTime.strptime(ut, '%s')
32
+ end
33
+
34
+ def self.decimals(rubyxl_cell)
35
+ number_format = rubyxl_cell.number_format
36
+ return nil unless number_format
37
+ format_code = number_format.format_code
38
+ i = format_code.reverse.index('.')
39
+ format_code[0 - i..-1].length if i
40
+ end
41
+
25
42
  def self.rubyxl_cell_to_border_hash(rubyxl_cell)
26
43
  {
27
44
  top: rubyxl_cell.nil? ? nil : rubyxl_cell.get_border(:top),
@@ -68,28 +85,71 @@ module Cell
68
85
  rubyxl_worksheet.merge_cells(row_index, column_index, merge_column_index, merge_row_index) if combined_hash_cell[:merge]
69
86
  rubyxl_worksheet.change_column_width(column_index, combined_hash_cell[:width]) if combined_hash_cell[:width]
70
87
 
71
- rubyxl_worksheet[row_index][column_index].change_font_name(combined_hash_cell[:font_style]) if combined_hash_cell[:font_style]
88
+ rubyxl_worksheet[row_index][column_index].change_font_name(combined_hash_cell[:font_name]) if combined_hash_cell[:font_name]
72
89
  rubyxl_worksheet[row_index][column_index].change_font_size(combined_hash_cell[:font_size]) if combined_hash_cell[:font_size]
73
90
  rubyxl_worksheet[row_index][column_index].change_fill(combined_hash_cell[:fill]) if combined_hash_cell[:fill]
74
91
  rubyxl_worksheet[row_index][column_index].change_horizontal_alignment(combined_hash_cell[:h_align]) if combined_hash_cell[:h_align]
75
92
  rubyxl_worksheet[row_index][column_index].change_font_bold(combined_hash_cell[:bold]) if combined_hash_cell[:bold]
76
93
 
77
- if combined_hash_cell[:border_all]
78
- rubyxl_worksheet[row_index][column_index].change_border('top' , combined_hash_cell[:border_all])
79
- rubyxl_worksheet[row_index][column_index].change_border('bottom' , combined_hash_cell[:border_all])
80
- rubyxl_worksheet[row_index][column_index].change_border('left' , combined_hash_cell[:border_all])
81
- rubyxl_worksheet[row_index][column_index].change_border('right' , combined_hash_cell[:border_all])
94
+ if combined_hash_cell[:border]
95
+ rubyxl_worksheet[row_index][column_index].change_border('top' , combined_hash_cell[:border][:top])
96
+ rubyxl_worksheet[row_index][column_index].change_border('bottom' , combined_hash_cell[:border][:bottom])
97
+ rubyxl_worksheet[row_index][column_index].change_border('left' , combined_hash_cell[:border][:left])
98
+ rubyxl_worksheet[row_index][column_index].change_border('right' , combined_hash_cell[:border][:right])
99
+ end
100
+ end
101
+
102
+ def self.add_rubyxl_cells(hash_cell, rubyxl_worksheet, row_index, column_index)
103
+ number_format = write_format(hash_cell)
104
+ if hash_cell[:formula]
105
+ if number_format
106
+ rubyxl_worksheet.add_cell(row_index, column_index, '', hash_cell[:formula])
107
+ .set_number_format(number_format)
108
+ else
109
+ rubyxl_worksheet.add_cell(row_index, column_index, '', hash_cell[:formula])
110
+ end
111
+ else
112
+ if number_format
113
+ cell_value = hash_cell[:value].is_a?(Date) ? date_to_num(hash_cell[:value]) : hash_cell[:value]
114
+ rubyxl_worksheet.add_cell(row_index, column_index, cell_value)
115
+ .set_number_format(number_format)
116
+ else
117
+ rubyxl_worksheet.add_cell(row_index, column_index, hash_cell[:value])
118
+ end
82
119
  end
83
120
  end
84
121
 
85
- def self.add_rubyxl_cells(combined_hash_cell, rubyxl_worksheet, row_index, column_index)
86
- if combined_hash_cell[:formula]
87
- rubyxl_worksheet.add_cell(row_index, column_index, '', combined_hash_cell[:formula]).set_number_format combined_hash_cell[:dp_2]
122
+ def self.write_format(hash_cell)
123
+ case hash_cell[:format]
124
+ when :number
125
+ hash_cell[:decimals] ? "0.#{ '0' * hash_cell[:decimals] }" : '0'
126
+ when :date
127
+ hash_cell[:date_format] ? hash_cell[:date_format] : 'dd/mm/yyyy'
128
+ when :time
129
+ hash_cell[:date_format] ? hash_cell[:date_format] : 'hh:mm:ss'
130
+ when :percentage
131
+ hash_cell[:decimals] ? "0.#{ '0' * hash_cell[:decimals] }%" : '0%'
88
132
  else
89
- rubyxl_worksheet.add_cell(row_index, column_index, combined_hash_cell[:value])
133
+ case hash_cell[:value].class.to_s
134
+ when 'Fixnum'
135
+ '0'
136
+ when 'Float'
137
+ value = hash_cell[:value].to_s
138
+ decimals = value[value.index('.') + 1..-1].length
139
+ "0.#{ '0' * decimals }"
140
+ when 'DateTime'
141
+ return 'dd/mm/yyyy hh:mm:ss'
142
+ else
143
+ nil
144
+ end
90
145
  end
91
146
  end
92
147
 
148
+ def self.date_to_num(date)
149
+ workbook = RubyXL::Workbook.new
150
+ workbook.date_to_num(date)
151
+ end
152
+
93
153
 
94
154
  ##################################
95
155
  ### VALIDATE HASH CELL ###
@@ -124,8 +184,10 @@ module Cell
124
184
  def self.valid_cell_keys
125
185
  %i[
126
186
  value
127
- number
187
+ format
188
+ date_format
128
189
  formula
190
+ decimals
129
191
  bold
130
192
  h_align
131
193
  v_align
data/lib/rxl/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Rxl
2
- VERSION = "0.4.1"
2
+ VERSION = "0.5.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rxl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ian McWilliams
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-02-16 00:00:00.000000000 Z
11
+ date: 2019-02-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler