nulogy-spreadsheet 0.6.5.7.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. data/.gitignore +3 -0
  2. data/GUIDE.txt +267 -0
  3. data/Gemfile +4 -0
  4. data/Gemfile.lock +18 -0
  5. data/History.txt +365 -0
  6. data/LICENSE.txt +619 -0
  7. data/Manifest.txt +62 -0
  8. data/README.txt +107 -0
  9. data/Rakefile +1 -0
  10. data/bin/xlsopcodes +18 -0
  11. data/lib/parseexcel.rb +27 -0
  12. data/lib/parseexcel/parseexcel.rb +75 -0
  13. data/lib/parseexcel/parser.rb +11 -0
  14. data/lib/spreadsheet.rb +79 -0
  15. data/lib/spreadsheet/column.rb +71 -0
  16. data/lib/spreadsheet/compatibility.rb +23 -0
  17. data/lib/spreadsheet/datatypes.rb +105 -0
  18. data/lib/spreadsheet/encodings.rb +57 -0
  19. data/lib/spreadsheet/excel.rb +88 -0
  20. data/lib/spreadsheet/excel/error.rb +26 -0
  21. data/lib/spreadsheet/excel/internals.rb +361 -0
  22. data/lib/spreadsheet/excel/internals/biff5.rb +17 -0
  23. data/lib/spreadsheet/excel/internals/biff8.rb +19 -0
  24. data/lib/spreadsheet/excel/offset.rb +41 -0
  25. data/lib/spreadsheet/excel/reader.rb +1173 -0
  26. data/lib/spreadsheet/excel/reader/biff5.rb +22 -0
  27. data/lib/spreadsheet/excel/reader/biff8.rb +199 -0
  28. data/lib/spreadsheet/excel/row.rb +92 -0
  29. data/lib/spreadsheet/excel/sst_entry.rb +46 -0
  30. data/lib/spreadsheet/excel/workbook.rb +80 -0
  31. data/lib/spreadsheet/excel/worksheet.rb +100 -0
  32. data/lib/spreadsheet/excel/writer.rb +1 -0
  33. data/lib/spreadsheet/excel/writer/biff8.rb +75 -0
  34. data/lib/spreadsheet/excel/writer/format.rb +253 -0
  35. data/lib/spreadsheet/excel/writer/workbook.rb +653 -0
  36. data/lib/spreadsheet/excel/writer/worksheet.rb +886 -0
  37. data/lib/spreadsheet/font.rb +92 -0
  38. data/lib/spreadsheet/format.rb +177 -0
  39. data/lib/spreadsheet/formula.rb +9 -0
  40. data/lib/spreadsheet/helpers.rb +11 -0
  41. data/lib/spreadsheet/link.rb +43 -0
  42. data/lib/spreadsheet/row.rb +132 -0
  43. data/lib/spreadsheet/workbook.rb +126 -0
  44. data/lib/spreadsheet/worksheet.rb +277 -0
  45. data/lib/spreadsheet/writer.rb +30 -0
  46. data/nulogy-spreadsheet.gemspec +21 -0
  47. data/test/data/test_changes.xls +0 -0
  48. data/test/data/test_copy.xls +0 -0
  49. data/test/data/test_datetime.xls +0 -0
  50. data/test/data/test_empty.xls +0 -0
  51. data/test/data/test_formula.xls +0 -0
  52. data/test/data/test_long_sst_record.xls +0 -0
  53. data/test/data/test_missing_row.xls +0 -0
  54. data/test/data/test_version_excel5.xls +0 -0
  55. data/test/data/test_version_excel95.xls +0 -0
  56. data/test/data/test_version_excel97.xls +0 -0
  57. data/test/excel/row.rb +35 -0
  58. data/test/excel/writer/workbook.rb +23 -0
  59. data/test/excel/writer/worksheet.rb +55 -0
  60. data/test/font.rb +163 -0
  61. data/test/integration.rb +1311 -0
  62. data/test/row.rb +33 -0
  63. data/test/suite.rb +17 -0
  64. data/test/workbook.rb +29 -0
  65. data/test/worksheet.rb +80 -0
  66. metadata +162 -0
@@ -0,0 +1,126 @@
1
+ require 'spreadsheet/format'
2
+ require 'spreadsheet/encodings'
3
+
4
+ module Spreadsheet
5
+ ##
6
+ # The Workbook class represents a Spreadsheet-Document and is the entry point
7
+ # for all Spreadsheet manipulation.
8
+ #
9
+ # Interesting Attributes:
10
+ # #default_format:: The default format used for all cells in this Workbook.
11
+ # that have no format set explicitly or in
12
+ # Row#default_format or Worksheet#default_format.
13
+ class Workbook
14
+ include Spreadsheet::Encodings
15
+ attr_reader :io, :worksheets, :formats, :fonts
16
+ attr_accessor :active_worksheet, :encoding, :default_format, :version
17
+ def initialize io = nil, opts={:default_format => Format.new}
18
+ @worksheets = []
19
+ @io = io
20
+ @fonts = []
21
+ @formats = []
22
+ if @default_format = opts[:default_format]
23
+ @formats.push @default_format
24
+ end
25
+ end
26
+ ##
27
+ # Add a Font to the Workbook. Used by the parser. You should not need to
28
+ # use this Method.
29
+ def add_font font
30
+ @fonts.push(font).uniq! if font
31
+ font
32
+ end
33
+ ##
34
+ # Add a Format to the Workbook. If you use Row#set_format, you should not
35
+ # need to use this Method.
36
+ def add_format format
37
+ @formats.push(format) if format && !@formats.include?(format)
38
+ format
39
+ end
40
+ ##
41
+ # Add a Worksheet to the Workbook.
42
+ def add_worksheet worksheet
43
+ worksheet.workbook = self
44
+ @worksheets.push worksheet
45
+ worksheet
46
+ end
47
+ ##
48
+ # Create a new Worksheet in this Workbook.
49
+ # Used without options this creates a Worksheet with the name 'WorksheetN'
50
+ # where the new Worksheet is the Nth Worksheet in this Workbook.
51
+ #
52
+ # Use the option <em>:name => 'My pretty Name'</em> to override this
53
+ # behavior.
54
+ def create_worksheet opts = {}
55
+ opts[:name] ||= client("Worksheet#{@worksheets.size.next}", 'UTF-8')
56
+ add_worksheet Worksheet.new(opts)
57
+ end
58
+ ##
59
+ # Returns the count of total worksheets present.
60
+ # Takes no arguments. Just returns the length of @worksheets array.
61
+ def sheet_count
62
+ @worksheets.length
63
+ end
64
+ ##
65
+ # The Font at _idx_
66
+ def font idx
67
+ @fonts[idx]
68
+ end
69
+ ##
70
+ # The Format at _idx_, or - if _idx_ is a String -
71
+ # the Format with name == _idx_
72
+ def format idx
73
+ case idx
74
+ when Integer
75
+ @formats[idx] || @default_format
76
+ when String
77
+ @formats.find do |fmt| fmt.name == idx end
78
+ end
79
+ end
80
+ def inspect
81
+ variables = (instance_variables - uninspect_variables).collect do |name|
82
+ "%s=%s" % [name, instance_variable_get(name)]
83
+ end.join(' ')
84
+ uninspect = uninspect_variables.collect do |name|
85
+ var = instance_variable_get name
86
+ "%s=%s[%i]" % [name, var.class, var.size]
87
+ end.join(' ')
88
+ sprintf "#<%s:0x%014x %s %s>", self.class, object_id,
89
+ variables, uninspect
90
+ end
91
+ def uninspect_variables # :nodoc:
92
+ %w{@formats @fonts @worksheets}
93
+ end
94
+ ##
95
+ # The Worksheet at _idx_, or - if _idx_ is a String -
96
+ # the Worksheet with name == _idx_
97
+ def worksheet idx
98
+ case idx
99
+ when Integer
100
+ @worksheets[idx]
101
+ when String
102
+ @worksheets.find do |sheet| sheet.name == idx end
103
+ end
104
+ end
105
+ ##
106
+ # Write this Workbook to a File, IO Stream or Writer Object. The latter will
107
+ # make more sense once there are more than just an Excel-Writer available.
108
+ def write io_path_or_writer
109
+ if io_path_or_writer.is_a? Writer
110
+ io_path_or_writer.write self
111
+ else
112
+ writer(io_path_or_writer).write(self)
113
+ end
114
+ end
115
+ ##
116
+ # Returns a new instance of the default Writer class for this Workbook (can
117
+ # only be an Excel::Writer::Workbook at this time)
118
+ def writer io_or_path, type=Excel, version=self.version
119
+ if type == Excel
120
+ Excel::Writer::Workbook.new io_or_path
121
+ else
122
+ raise NotImplementedError, "No Writer defined for #{type}"
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,277 @@
1
+ require 'date'
2
+ require 'spreadsheet/column'
3
+ require 'spreadsheet/encodings'
4
+ require 'spreadsheet/row'
5
+
6
+ module Spreadsheet
7
+ ##
8
+ # The Worksheet class. Contains most of the Spreadsheet data in Rows.
9
+ #
10
+ # Interesting Attributes
11
+ # #name :: The Name of this Worksheet.
12
+ # #default_format:: The default format used for all cells in this Workhseet
13
+ # that have no format set explicitly or in
14
+ # Row#default_format.
15
+ # #rows :: The Rows in this Worksheet. It is not recommended to
16
+ # Manipulate this Array directly. If you do, call
17
+ # #updated_from with the smallest modified index.
18
+ # #columns :: The Column formatting in this Worksheet. Column
19
+ # instances may appear at more than one position in #columns.
20
+ # If you modify a Column directly, your changes will be
21
+ # reflected in all those positions.
22
+ # #selected :: When a user chooses to print a Workbook, Excel will include
23
+ # all selected Worksheets. If no Worksheet is selected at
24
+ # Workbook#write, then the first Worksheet is selected by
25
+ # default.
26
+ class Worksheet
27
+ include Spreadsheet::Encodings
28
+ include Enumerable
29
+ attr_accessor :name, :selected, :workbook
30
+ attr_reader :rows, :columns
31
+ def initialize opts={}
32
+ @default_format = nil
33
+ @selected = opts[:selected]
34
+ @dimensions = [0,0,0,0]
35
+ @name = opts[:name] || 'Worksheet'
36
+ @workbook = opts[:workbook]
37
+ @rows = []
38
+ @columns = []
39
+ @links = {}
40
+ end
41
+ def active # :nodoc:
42
+ warn "Worksheet#active is deprecated. Please use Worksheet#selected instead."
43
+ selected
44
+ end
45
+ def active= selected # :nodoc:
46
+ warn "Worksheet#active= is deprecated. Please use Worksheet#selected= instead."
47
+ self.selected = selected
48
+ end
49
+ ##
50
+ # Add a Format to the Workbook. If you use Row#set_format, you should not
51
+ # need to use this Method.
52
+ def add_format fmt
53
+ @workbook.add_format fmt if fmt
54
+ end
55
+ ##
56
+ # Get the enriched value of the Cell at _row_, _column_.
57
+ # See also Worksheet#[], Row#[].
58
+ def cell row, column
59
+ row(row)[column]
60
+ end
61
+ ##
62
+ # Returns the Column at _idx_.
63
+ def column idx
64
+ @columns[idx] || Column.new(idx, default_format, :worksheet => self)
65
+ end
66
+ ##
67
+ # The number of columns in this Worksheet which contain data.
68
+ def column_count
69
+ dimensions[3] - dimensions[2]
70
+ end
71
+ def column_updated idx, column
72
+ @columns[idx] = column
73
+ end
74
+ ##
75
+ # Delete the Row at _idx_ (0-based) from this Worksheet.
76
+ def delete_row idx
77
+ res = @rows.delete_at idx
78
+ updated_from idx
79
+ res
80
+ end
81
+ ##
82
+ # The default Format of this Worksheet, if you have set one.
83
+ # Returns the Workbook's default Format otherwise.
84
+ def default_format
85
+ @default_format || @workbook.default_format
86
+ end
87
+ ##
88
+ # Set the default Format of this Worksheet.
89
+ def default_format= format
90
+ @default_format = format
91
+ add_format format
92
+ format
93
+ end
94
+ ##
95
+ # Dimensions:: [ first used row, first unused row,
96
+ # first used column, first unused column ]
97
+ # ( First used means that all rows or columns before that are
98
+ # empty. First unused means that this and all following rows
99
+ # or columns are empty. )
100
+ def dimensions
101
+ @dimensions || recalculate_dimensions
102
+ end
103
+ ##
104
+ # If no argument is given, #each iterates over all used Rows (from the first
105
+ # used Row until but omitting the first unused Row, see also #dimensions).
106
+ #
107
+ # If the argument skip is given, #each iterates from that row until but
108
+ # omitting the first unused Row, effectively skipping the first _skip_ Rows
109
+ # from the top of the Worksheet.
110
+ def each skip=dimensions[0], &block
111
+ skip.upto(dimensions[1] - 1) do |idx|
112
+ block.call row(idx)
113
+ end
114
+ end
115
+ def encoding # :nodoc:
116
+ @workbook.encoding
117
+ end
118
+ ##
119
+ # Sets the default Format of the column at _idx_.
120
+ #
121
+ # _idx_ may be an Integer, or an Enumerable that iterates over a number of
122
+ # Integers.
123
+ #
124
+ # _format_ is a Format, or nil if you want to remove the Formatting at _idx_
125
+ #
126
+ # Returns an instance of Column if _idx_ is an Integer, an Array of Columns
127
+ # otherwise.
128
+ def format_column idx, format=nil, opts={}
129
+ opts[:worksheet] = self
130
+ res = case idx
131
+ when Integer
132
+ column = nil
133
+ if format
134
+ column = Column.new(idx, format, opts)
135
+ end
136
+ @columns[idx] = column
137
+ else
138
+ idx.collect do |col| format_column col, format, opts end
139
+ end
140
+ shorten @columns
141
+ res
142
+ end
143
+ ##
144
+ # Formats all Date, DateTime and Time cells with _format_ or the default
145
+ # formats:
146
+ # - 'DD.MM.YYYY' for Date
147
+ # - 'DD.MM.YYYY hh:mm:ss' for DateTime and Time
148
+ def format_dates! format=nil
149
+ each do |row|
150
+ row.each_with_index do |value, idx|
151
+ unless row.formats[idx] || row.format(idx).date_or_time?
152
+ numfmt = case value
153
+ when DateTime, Time
154
+ format || client('DD.MM.YYYY hh:mm:ss', 'UTF-8')
155
+ when Date
156
+ format || client('DD.MM.YYYY', 'UTF-8')
157
+ end
158
+ case numfmt
159
+ when Format
160
+ row.set_format idx, numfmt
161
+ when String
162
+ fmt = row.format(idx).dup
163
+ fmt.number_format = numfmt
164
+ row.set_format idx, fmt
165
+ end
166
+ end
167
+ end
168
+ end
169
+ end
170
+ ##
171
+ # Insert a Row at _idx_ (0-based) containing _cells_
172
+ def insert_row idx, cells=[]
173
+ res = @rows.insert idx, Row.new(self, idx, cells)
174
+ updated_from idx
175
+ res
176
+ end
177
+ def inspect
178
+ names = instance_variables
179
+ names.delete '@rows'
180
+ variables = names.collect do |name|
181
+ "%s=%s" % [name, instance_variable_get(name)]
182
+ end.join(' ')
183
+ sprintf "#<%s:0x%014x %s @rows[%i]>", self.class, object_id,
184
+ variables, row_count
185
+ end
186
+ ## The last Row containing any data
187
+ def last_row
188
+ row(last_row_index)
189
+ end
190
+ ## The index of the last Row containing any data
191
+ def last_row_index
192
+ [dimensions[1] - 1, 0].max
193
+ end
194
+ ##
195
+ # Replace the Row at _idx_ with the following arguments. Like #update_row,
196
+ # but truncates the Row if there are fewer arguments than Cells in the Row.
197
+ def replace_row idx, *cells
198
+ if(row = @rows[idx]) && cells.size < row.size
199
+ cells.concat Array.new(row.size - cells.size)
200
+ end
201
+ update_row idx, *cells
202
+ end
203
+ ##
204
+ # The Row at _idx_ or a new Row.
205
+ def row idx
206
+ @rows[idx] || Row.new(self, idx)
207
+ end
208
+ ##
209
+ # The number of Rows in this Worksheet which contain data.
210
+ def row_count
211
+ dimensions[1] - dimensions[0]
212
+ end
213
+ ##
214
+ # Tell Worksheet that the Row at _idx_ has been updated and the #dimensions
215
+ # need to be recalculated. You should not need to call this directly.
216
+ def row_updated idx, row
217
+ @dimensions = nil
218
+ @rows[idx] = row
219
+ end
220
+ ##
221
+ # Updates the Row at _idx_ with the following arguments.
222
+ def update_row idx, *cells
223
+ res = if row = @rows[idx]
224
+ row[0, cells.size] = cells
225
+ row
226
+ else
227
+ Row.new self, idx, cells
228
+ end
229
+ row_updated idx, res
230
+ res
231
+ end
232
+ ##
233
+ # Renumbers all Rows starting at _idx_ and calls #row_updated for each of
234
+ # them.
235
+ def updated_from index
236
+ index.upto(@rows.size - 1) do |idx|
237
+ row = row(idx)
238
+ row.idx = idx
239
+ row_updated idx, row
240
+ end
241
+ end
242
+ ##
243
+ # Get the enriched value of the Cell at _row_, _column_.
244
+ # See also Worksheet#cell, Row#[].
245
+ def [] row, column
246
+ row(row)[column]
247
+ end
248
+ ##
249
+ # Set the value of the Cell at _row_, _column_ to _value_.
250
+ # See also Row#[]=.
251
+ def []= row, column, value
252
+ row(row)[column] = value
253
+ end
254
+ private
255
+ def index_of_first ary # :nodoc:
256
+ return unless ary
257
+ ary.index(ary.find do |elm| elm end)
258
+ end
259
+ def recalculate_dimensions # :nodoc:
260
+ shorten @rows
261
+ @dimensions = []
262
+ @dimensions[0] = index_of_first(@rows) || 0
263
+ @dimensions[1] = @rows.size
264
+ compact = @rows.compact
265
+ @dimensions[2] = compact.collect do |row| row.first_used end.compact.min || 0
266
+ @dimensions[3] = compact.collect do |row| row.first_unused end.max || 0
267
+ @dimensions
268
+ end
269
+ def shorten ary # :nodoc:
270
+ return unless ary
271
+ while !ary.empty? && !ary.last
272
+ ary.pop
273
+ end
274
+ ary unless ary.empty?
275
+ end
276
+ end
277
+ end
@@ -0,0 +1,30 @@
1
+ module Spreadsheet
2
+ ##
3
+ # Parent Class for all Writers. Implements the copying of unmodified
4
+ # Spreadsheet documents.
5
+ class Writer
6
+ def initialize io_or_path
7
+ @io_or_path = io_or_path
8
+ end
9
+ def write workbook
10
+ if @io_or_path.respond_to? :seek
11
+ @io_or_path.binmode
12
+ write_workbook workbook, @io_or_path
13
+ else
14
+ File.open(@io_or_path, "wb+") do |fh|
15
+ write_workbook workbook, fh
16
+ end
17
+ end
18
+ end
19
+ private
20
+ def write_workbook workbook, io
21
+ reader = workbook.io
22
+ unless io == reader
23
+ reader.rewind
24
+ data = reader.read
25
+ io.rewind
26
+ io.write data
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "nulogy-spreadsheet"
6
+ s.version = "0.6.5.7.2"
7
+ s.summary = "The Spreadsheet Library is designed to read and write Spreadsheet Documents"
8
+ s.description = "As of version 0.6.0, only Microsoft Excel compatible spreadsheets are supported"
9
+ s.authors = ["Masaomi Hatakeyama", "Zeno R.R. Davatz", "Clemens Park"]
10
+ s.email = "sskirby@gmail.com"
11
+ s.homepage = "https://github.com/nulogy/spreadsheet"
12
+ s.rubyforge_project = "nulogy-spreadsheet"
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ s.require_paths = ["lib"]
18
+
19
+ s.add_dependency('ruby-ole')
20
+ s.add_development_dependency('rake')
21
+ end