ru_excel 0.0.6

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.
@@ -0,0 +1,466 @@
1
+ dir = File.dirname(__FILE__)
2
+ require dir+'/biff_records'
3
+ require dir+'/bitmap'
4
+ require dir+'/formatting'
5
+ require dir+'/style'
6
+ require dir+'/deco'
7
+ require dir+'/row'
8
+ require dir+'/column'
9
+ require dir+'/cell'
10
+ require dir+'/workbook'
11
+
12
+
13
+ =begin
14
+ BOF
15
+ UNCALCED
16
+ INDEX
17
+ Calculation Settings Block
18
+ PRINTHEADERS
19
+ PRINTGRIDLINES
20
+ GRIDSET
21
+ GUTS
22
+ DEFAULTROWHEIGHT
23
+ WSBOOL
24
+ Page Settings Block
25
+ Worksheet Protection Block
26
+ DEFCOLWIDTH
27
+ COLINFO
28
+ SORT
29
+ DIMENSIONS
30
+ Row Blocks
31
+ WINDOW2
32
+ SCL
33
+ PANE
34
+ SELECTION
35
+ STANDARDWIDTH
36
+ MERGEDCELLS
37
+ LABELRANGES
38
+ PHONETIC
39
+ Conditional Formatting Table
40
+ Hyperlink Table
41
+ Data Validity Table
42
+ SHEETLAYOUT (BIFF8X only)
43
+ SHEETPROTECTION (BIFF8X only)
44
+ RANGEPROTECTION (BIFF8X only)
45
+ EOF
46
+ =end
47
+
48
+ module Excel
49
+ class Worksheet
50
+ extend Deco
51
+ #################################################################
52
+ ## Constructor
53
+ #################################################################
54
+ def initialize(sheetname, parent_book)
55
+ @name = sheetname
56
+ @parent = parent_book
57
+
58
+ @rows = {}
59
+ @cols = {}
60
+ @merged_ranges = []
61
+ @bmp_rec = ''
62
+
63
+ @show_formulas = 0
64
+ @show_grid = 1
65
+ @show_headers = 1
66
+ @panes_frozen = 0
67
+ @show_empty_as_zero = 1
68
+ @auto_colour_grid = 1
69
+ @cols_right_to_left = 0
70
+ @show_outline = 1
71
+ @remove_splits = 0
72
+ @selected = 0
73
+ @hidden = 0
74
+ @page_preview = 0
75
+
76
+ @first_visible_row = 0
77
+ @first_visible_col = 0
78
+ @grid_colour = 0x40
79
+ @preview_magn = 0
80
+ @normal_magn = 0
81
+
82
+ @vert_split_pos = nil
83
+ @horz_split_pos = nil
84
+ @vert_split_first_visible = nil
85
+ @horz_split_first_visible = nil
86
+ @split_active_pane =
87
+
88
+ @row_gut_width = 0
89
+ @col_gut_height = 0
90
+
91
+ @show_auto_page_breaks = 1
92
+ @dialogue_sheet = 0
93
+ @auto_style_outline = 0
94
+ @outline_below = 0
95
+ @outline_right = 0
96
+ @fit_num_pages = 0
97
+ @show_row_outline = 1
98
+ @show_col_outline = 1
99
+ @alt_expr_eval = 0
100
+ @alt_formula_entries = 0
101
+
102
+ @row_default_height = 0x00FF
103
+ @col_default_width = 0x0008
104
+
105
+ @calc_mode = 1
106
+ @calc_count = 0x0064
107
+ @RC_ref_mode = 1
108
+ @iterations_on = 0
109
+ @delta = 0.001
110
+ @save_recalc = 0
111
+
112
+ @print_headers = 0
113
+ @print_grid = 0
114
+ @grid_set = 1
115
+ @vert_page_breaks = []
116
+ @horz_page_breaks = []
117
+ @header_str = '&P'
118
+ @footer_str = '&F'
119
+ @print_centered_vert = 0
120
+ @print_centered_horz = 1
121
+ @left_margin = 0.3 #0.5
122
+ @right_margin = 0.3 #0.5
123
+ @top_margin = 0.61 #1.0
124
+ @bottom_margin = 0.37 #1.0
125
+ @paper_size_code = 9 # A4
126
+ @print_scaling = 100
127
+ @start_page_number = 1
128
+ @fit_width_to_pages = 1
129
+ @fit_height_to_pages = 1
130
+ @print_in_rows = 1
131
+ @portrait = 1
132
+ @print_not_colour = 0
133
+ @print_draft = 0
134
+ @print_notes = 0
135
+ @print_notes_at_end = 0
136
+ @print_omit_errors = 0
137
+ @print_hres = 0x012C # 300 dpi
138
+ @print_vres = 0x012C # 300 dpi
139
+ @header_margin = 0.1
140
+ @footer_margin = 0.1
141
+ @copies_num = 1
142
+
143
+ @wnd_protect = 0
144
+ @obj_protect = 0
145
+ @protect = 0
146
+ @scen_protect = 0
147
+ @password = ''
148
+ end
149
+ #################################################################
150
+ ## Properties, "getters", "setters"
151
+ #################################################################
152
+ def calc_mode=(value)
153
+ @calc_mode = value & 0x03
154
+ end
155
+ def calc_mode
156
+ return @calc_mode
157
+ end
158
+ string_accessor :name, :header_str, :footer_str, :password
159
+ float_accessor :delta, :left_margin, :right_margin, :top_margin, :bottom_margin
160
+ float_accessor :header_margin, :footer_margin
161
+ array_accessor :vert_page_breaks, :horz_page_breaks
162
+
163
+ attr_reader :parent, :rows, :cols, :merged_ranges, :bmp_rec
164
+ bool_int_accessor :print_colour, :show_formulas, :show_grid, :show_headers
165
+ bool_int_accessor :panes_frozen, :show_empty_as_zero, :auto_colour_grid
166
+ bool_int_accessor :cols_right_to_left, :show_outline, :remove_splits, :selected
167
+ bool_int_accessor :hidden, :page_preview, :show_auto_page_breaks
168
+ bool_int_accessor :dialogue_sheet, :auto_style_outline, :outline_below
169
+ bool_int_accessor :outline_right, :show_row_outline, :show_col_outline
170
+ bool_int_accessor :alt_expr_eval, :alt_formula_entries, :RC_ref_mode
171
+ bool_int_accessor :iterations_on, :save_recalc, :print_headers, :print_grid
172
+ bool_int_accessor :print_centered_vert, :print_centered_horz, :print_in_rows
173
+ bool_int_accessor :portrait, :print_not_colour, :print_draft, :print_notes
174
+ bool_int_accessor :print_notes_at_end, :print_omit_errors, :wnd_protect
175
+ bool_int_accessor :obj_protect, :protect, :scen_protect
176
+
177
+ int_accessor :first_visible_row, :first_visible_col, :grid_colour, :preview_magn
178
+ int_accessor :normal_magn, :fit_num_pages, :row_default_height, :print_scaling
179
+ int_accessor :col_default_width, :calc_count, :paper_size_code, :print_hres
180
+ int_accessor :start_page_number, :fit_width_to_pages, :fit_height_to_pages
181
+ int_accessor :print_vres, :copies_num
182
+
183
+ absint_accessor :vert_split_pos, :horz_split_pos, :vert_split_first_visible
184
+ absint_accessor :horz_split_first_visible
185
+
186
+ attr_reader :parent
187
+
188
+ ##################################################################
189
+ ## Methods
190
+ ##################################################################
191
+
192
+ def write(r, c, label="", style=XFStyle.new())
193
+ row(r).write(c, label, style)
194
+ end
195
+
196
+ def merge(r1, r2, c1, c2, style=Style.XFStyle())
197
+ for r in r1..r2
198
+ row(r).write_blanks(c1, c2, style)
199
+ end
200
+ @merged_ranges << [r1, r2, c1, c2]
201
+ end
202
+
203
+ def write_merge(r1, r2, c1, c2, label="", style=XFStyle.new())
204
+ merge(r1, r2, c1, c2, style)
205
+ write(r1, c1, label, style)
206
+ end
207
+
208
+ def insert_bitmap(filename, row, col, x = 0, y = 0, scale_x = 1, scale_y = 1)
209
+ bmp = BiffRecord.imDataBmpRecord(filename)
210
+ obj = BiffRecord.objBmpRecord(row, col, self, bmp, x, y, scale_x, scale_y)
211
+
212
+ @bmp_rec += obj + bmp
213
+ end
214
+ def col(indx)
215
+ @cols[indx] ||= Column.new(indx, self)
216
+ end
217
+
218
+ def row(indx)
219
+ @rows[indx] ||= Row.new(indx, self)
220
+ end
221
+
222
+ def row_height(row) # in pixels
223
+ if (row = @rows[row])
224
+ return row.get_height_in_pixels()
225
+ else
226
+ return 17
227
+ end
228
+ end
229
+
230
+ def col_width(col) # in pixels
231
+ #if col in @cols
232
+ # return @cols[col].width_in_pixels()
233
+ #else
234
+ return 64
235
+ end
236
+
237
+ def labels_count
238
+ result = 0
239
+ for r, row in @rows
240
+ result += row.get_str_count()
241
+ end
242
+ return result
243
+ end
244
+
245
+ ##################################################################
246
+ ## BIFF records generation
247
+ ##################################################################
248
+
249
+ def _bof_rec
250
+ BiffRecord.biff8BOFRecord(BiffRecord::WORKSHEET)
251
+ end
252
+
253
+ def _guts_rec
254
+ row_visible_levels = 0
255
+ if @rows.length != 0
256
+ row_visible_levels = @rows.map{|k,r| r.level}.max + 1
257
+ end
258
+
259
+ col_visible_levels = 0
260
+ if @cols.length != 0
261
+ col_visible_levels = @cols.map{|k,c| c.level}.max + 1
262
+ end
263
+
264
+ BiffRecord.gutsRecord(@row_gut_width, @col_gut_height, row_visible_levels, col_visible_levels)
265
+ end
266
+
267
+ def _wsbool_rec
268
+ options = 0x00
269
+ options |= (@show_auto_page_breaks & 0x01) << 0
270
+ options |= (@dialogue_sheet & 0x01) << 4
271
+ options |= (@auto_style_outline & 0x01) << 5
272
+ options |= (@outline_below & 0x01) << 6
273
+ options |= (@outline_right & 0x01) << 7
274
+ options |= (@fit_num_pages & 0x01) << 8
275
+ options |= (@show_row_outline & 0x01) << 10
276
+ options |= (@show_col_outline & 0x01) << 11
277
+ options |= (@alt_expr_eval & 0x01) << 14
278
+ options |= (@alt_formula_entries & 0x01) << 15
279
+
280
+ BiffRecord.wsBoolRecord(options)
281
+ end
282
+
283
+ def _eof_rec
284
+ BiffRecord.eofRecord()
285
+ end
286
+
287
+ def _colinfo_rec
288
+ @cols.map{|k, col| col.get_biff_record}.join('')
289
+ end
290
+
291
+ def _dimensions_rec
292
+ first_used_row = 0
293
+ last_used_row = 0
294
+ first_used_col = 0
295
+ last_used_col = 0
296
+ if @rows.length > 0
297
+ first_used_row = @rows.min[0]
298
+ last_used_row = @rows.max[0]
299
+ first_used_col = 0xFFFFFFFF
300
+ last_used_col = 0
301
+ for k,r in @rows
302
+ _min = r.get_min_col()
303
+ _max = r.get_max_col()
304
+ if _min < first_used_col
305
+ first_used_col = _min
306
+ end
307
+ if _max > last_used_col
308
+ last_used_col = _max
309
+ end
310
+ end
311
+ end
312
+
313
+ BiffRecord.dimensionsRecord(first_used_row, last_used_row, first_used_col, last_used_col)
314
+ end
315
+
316
+ def _window2_rec
317
+ options = 0
318
+ options |= (@show_formulas & 0x01) << 0
319
+ options |= (@show_grid & 0x01) << 1
320
+ options |= (@show_headers & 0x01) << 2
321
+ options |= (@panes_frozen & 0x01) << 3
322
+ options |= (@show_empty_as_zero & 0x01) << 4
323
+ options |= (@auto_colour_grid & 0x01) << 5
324
+ options |= (@cols_right_to_left & 0x01) << 6
325
+ options |= (@show_outline & 0x01) << 7
326
+ options |= (@remove_splits & 0x01) << 8
327
+ options |= (@selected & 0x01) << 9
328
+ options |= (@hidden & 0x01) << 10
329
+ options |= (@page_preview & 0x01) << 11
330
+
331
+ BiffRecord.window2Record(options, @first_visible_row, @first_visible_col,
332
+ @grid_colour,
333
+ @preview_magn, @normal_magn)
334
+ end
335
+
336
+ def _panes_rec
337
+ return "" if @vert_split_pos == nil && @horz_split_pos == nil
338
+
339
+ @vert_split_pos ||= 0
340
+ @horz_split_pos ||= 0
341
+
342
+ if @panes_frozen
343
+ @vert_split_first_visible ||= @vert_split_pos
344
+ @horz_split_first_visible ||= @horz_split_pos
345
+ else
346
+ @vert_split_first_visible ||= 0
347
+ @horz_split_first_visible ||= 0
348
+ # inspired by pyXLWriter
349
+ @horz_split_pos = 20*@horz_split_pos + 255
350
+ @vert_split_pos = 113.879*@vert_split_pos + 390
351
+ end
352
+
353
+ @split_active_pane = (@vert_split_pos > 0 ? 0 : 2) + (@horz_split_pos > 0 ? 0 : 1)
354
+
355
+ BiffRecord.panesRecord(@vert_split_pos,
356
+ @horz_split_pos,
357
+ @horz_split_first_visible,
358
+ @vert_split_first_visible,
359
+ @split_active_pane)
360
+ end
361
+
362
+ def _row_blocks_rec
363
+ # this function takes almost 99% of overall execution time
364
+ # when file is saved
365
+ # return ''
366
+ result = []
367
+ for k, r in @rows
368
+ result << r.get_row_biff_data
369
+ result << r.get_cells_biff_data
370
+ end
371
+ result.join('')
372
+ end
373
+
374
+ def _merged_rec
375
+ BiffRecord.mergedCellsRecord(@merged_ranges)
376
+ end
377
+
378
+ def _bitmaps_rec
379
+ @bmp_rec
380
+ end
381
+
382
+ def _calc_settings_rec
383
+ result = ''
384
+ result << BiffRecord.calcModeRecord(@calc_mode & 0x01)
385
+ result << BiffRecord.calcCountRecord(@calc_count & 0xFFFF)
386
+ result << BiffRecord.refModeRecord(@RC_ref_mode & 0x01)
387
+ result << BiffRecord.iterationRecord(@iterations_on & 0x01)
388
+ result << BiffRecord.deltaRecord(@delta)
389
+ result << BiffRecord.saveRecalcRecord(@save_recalc & 0x01)
390
+ result
391
+ end
392
+
393
+ def _print_settings_rec
394
+ result = ''
395
+ result << BiffRecord.printHeadersRecord(@print_headers)
396
+ result << BiffRecord.printGridLinesRecord(@print_grid)
397
+ result << BiffRecord.gridSetRecord(@grid_set)
398
+ result << BiffRecord.horizontalPageBreaksRecord(@horz_page_breaks)
399
+ result << BiffRecord.verticalPageBreaksRecord(@vert_page_breaks)
400
+ result << BiffRecord.headerRecord(@header_str)
401
+ result << BiffRecord.footerRecord(@footer_str)
402
+ result << BiffRecord.hCenterRecord(@print_centered_horz)
403
+ result << BiffRecord.vCenterRecord(@print_centered_vert)
404
+ result << BiffRecord.leftMarginRecord(@left_margin)
405
+ result << BiffRecord.rightMarginRecord(@right_margin)
406
+ result << BiffRecord.topMarginRecord(@top_margin)
407
+ result << BiffRecord.bottomMarginRecord(@bottom_margin)
408
+
409
+ setup_page_options = (@print_in_rows & 0x01) << 0
410
+ setup_page_options |= (@portrait & 0x01) << 1
411
+ setup_page_options |= (0x00 & 0x01) << 2
412
+ setup_page_options |= (@print_not_colour & 0x01) << 3
413
+ setup_page_options |= (@print_draft & 0x01) << 4
414
+ setup_page_options |= (@print_notes & 0x01) << 5
415
+ setup_page_options |= (0x00 & 0x01) << 6
416
+ setup_page_options |= (0x01 & 0x01) << 7
417
+ setup_page_options |= (@print_notes_at_end & 0x01) << 9
418
+ setup_page_options |= (@print_omit_errors & 0x03) << 10
419
+
420
+ result << BiffRecord.setupPageRecord(@paper_size_code,
421
+ @print_scaling,
422
+ @start_page_number,
423
+ @fit_width_to_pages,
424
+ @fit_height_to_pages,
425
+ setup_page_options,
426
+ @print_hres,
427
+ @print_vres,
428
+ @header_margin,
429
+ @footer_margin,
430
+ @copies_num)
431
+ result
432
+ end
433
+
434
+ def _protection_rec
435
+ result = ''
436
+ result << BiffRecord.protectRecord(@protect)
437
+ result << BiffRecord.scenProtectRecord(@scen_protect)
438
+ result << BiffRecord.windowProtectRecord(@wnd_protect)
439
+ result << BiffRecord.objectProtectRecord(@obj_protect)
440
+ result << BiffRecord.passwordRecord(@password)
441
+ result
442
+ end
443
+
444
+ def get_biff_data
445
+ result = ''
446
+ result << _bof_rec()
447
+ result << _calc_settings_rec()
448
+ result << _guts_rec()
449
+ result << _wsbool_rec()
450
+ result << _colinfo_rec()
451
+ result << _dimensions_rec()
452
+ result << _print_settings_rec()
453
+ result << _protection_rec()
454
+ result << _row_blocks_rec()
455
+ result << _merged_rec()
456
+ result << _bitmaps_rec()
457
+ result << _window2_rec()
458
+ result << _panes_rec()
459
+ result << _eof_rec()
460
+ result
461
+ end
462
+ end
463
+ end
464
+
465
+
466
+
data/lib/ru_excel.rb ADDED
@@ -0,0 +1,16 @@
1
+ require 'iconv'
2
+ module Excel
3
+ ICONV = {}
4
+ def self.encoding
5
+ @encoding
6
+ end
7
+ def self.encoding=(enc)
8
+ @encoding = enc
9
+ (ICONV[:to_unicode] = Iconv.new('utf16le', enc)).iconv('z')
10
+ (ICONV[:from_unicode] = Iconv.new(enc, 'utf16le')).iconv("z\0")
11
+ end
12
+ self.encoding= 'cp1251'
13
+ (ICONV[:check_ascii] = Iconv.new('ascii','ascii')).iconv('z')
14
+ (ICONV[:check_unicode] = Iconv.new('utf16le','utf16le')).iconv("z\0")
15
+ end
16
+ require 'ru_excel/workbook'
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ru_excel
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.6
6
+ platform: ruby
7
+ authors:
8
+ - Sokolov Yura aka funny_falcon
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-05-18 00:00:00 Z
14
+ dependencies: []
15
+
16
+ description: Port of pyExcelerator tunned for faster .xls generation
17
+ email: funny.falcon@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README
24
+ files:
25
+ - README
26
+ - Rakefile
27
+ - VERSION
28
+ - examples/big-16Mb_test.rb
29
+ - examples/test_multiline.rb
30
+ - examples/test_utf8.rb
31
+ - lib/ru_excel.rb
32
+ - lib/ru_excel/biff_records.rb
33
+ - lib/ru_excel/bitmap.rb
34
+ - lib/ru_excel/cell.rb
35
+ - lib/ru_excel/column.rb
36
+ - lib/ru_excel/compound_doc.rb
37
+ - lib/ru_excel/deco.rb
38
+ - lib/ru_excel/excel_magic.rb
39
+ - lib/ru_excel/formatting.rb
40
+ - lib/ru_excel/row.rb
41
+ - lib/ru_excel/style.rb
42
+ - lib/ru_excel/unicode_utils.rb
43
+ - lib/ru_excel/workbook.rb
44
+ - lib/ru_excel/worksheet.rb
45
+ homepage: http://github.com/funny-falcon/ru_excel
46
+ licenses: []
47
+
48
+ post_install_message:
49
+ rdoc_options: []
50
+
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: "0"
65
+ requirements: []
66
+
67
+ rubyforge_project: ru-excel
68
+ rubygems_version: 1.7.2
69
+ signing_key:
70
+ specification_version: 3
71
+ summary: Fast writting of MsExcel files (port of pyExcelerator)
72
+ test_files: []
73
+