axlsx 1.2.0 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -25,7 +25,7 @@ Axlsx: Office Open XML Spreadsheet Generation
25
25
 
26
26
  **Rubinius Version**: rubinius 2.0.0dev * lower versions may run, this gem always tests against head.
27
27
 
28
- **Release Date**: August 5th 2012
28
+ **Release Date**: August 12th 2012
29
29
 
30
30
  If you are working in rails, or with active record see:
31
31
  * http://github.com/randym/acts_as_xlsx
@@ -145,6 +145,10 @@ This gem has 100% test coverage using test/unit. To execute tests for this gem,
145
145
 
146
146
  #Change log
147
147
  ---------
148
+ - **August.12.12**: 1.2.1
149
+ - Add support for hyperlinks in worksheets
150
+ - Fix example that was using old style cell merging with concact.
151
+ - Fix bug that occurs when calculating the font_size for cells that use a user specified style which does not define sz
148
152
  - **August.5.12**: 1.2.0
149
153
  - rebuilt worksheet serialization to clean up the code base a bit.
150
154
  - added data labels for charts
@@ -229,6 +233,7 @@ done without the help of the people below.
229
233
 
230
234
  [straydogstudio](https://github.com/straydocstudio) - For making an AWESOME axlsx templating gem for rails.
231
235
 
236
+ [MitchellAJ](https://github.com/MitchellAJ) - For catching a bug in font_size calculations, finding some old code in an example and above all for reporting all of that brilliantly
232
237
  #Copyright and License
233
238
  ----------
234
239
 
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby -w -s
2
2
  # -*- coding: utf-8 -*-
3
- # $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
3
+ $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
4
4
 
5
5
  #```ruby
6
6
  require 'axlsx'
@@ -202,8 +202,32 @@ wb.add_worksheet(:name => "Automatic cell types") do |sheet|
202
202
  sheet.add_row ["Date", "Time", "String", "Boolean", "Float", "Integer"]
203
203
  sheet.add_row [Date.today, Time.now, "value", true, 0.1, 1], :style => [date_format, time_format]
204
204
  end
205
+
206
+
207
+ # Hyperlinks in worksheet
208
+ wb.add_worksheet(:name => 'hyperlinks') do |sheet|
209
+ # external references
210
+ sheet.add_row ['axlsx']
211
+ sheet.add_hyperlink :location => 'https://github.com/randym/axlsx', :ref => sheet.rows.first.cells.first
212
+
213
+ # internal references
214
+ sheet.add_row ['next sheet']
215
+ end
216
+
217
+ wb.add_worksheet(:name => 'Next Sheet') do |sheet|
218
+ sheet.add_row ['hello!']
219
+ end
205
220
  #```
206
221
 
222
+ ##Number formatting and currency
223
+ wb.add_worksheet(:name => "Formats and Currency") do |sheet|
224
+ currency = wb.styles.add_style :num_fmt => 5
225
+ red_negative = wb.styles.add_style :num_fmt => 8
226
+ comma = wb.styles.add_style :num_fmt => 3
227
+ super_funk = wb.styles.add_style :format_code => '[Green]"super funk: " #'
228
+ sheet.add_row %w(Currency RedNegative, Comma Custom)
229
+ sheet.add_row [1500, -122.34, 123456789, 594829], :style=> [currency, red_negative, comma, super_funk]
230
+ end
207
231
 
208
232
  ##Generating A Bar Chart
209
233
 
Binary file
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env ruby -w -s
2
+ # -*- coding: utf-8 -*-
3
+ $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
4
+
5
+ #```ruby
6
+ require 'axlsx'
7
+
8
+ p = Axlsx::Package.new
9
+ wb = p.workbook
10
+ wb.add_worksheet(:name => 'hyperlinks') do |sheet|
11
+ # external references
12
+ sheet.add_row ['axlsx']
13
+ sheet.add_hyperlink :location => 'https://github.com/randym/axlsx', :ref => sheet.rows.first.cells.first
14
+ # internal references
15
+ sheet.add_row ['next sheet']
16
+ sheet.add_hyperlink :location => "'Next Sheet'!A1", :target => :sheet, :ref => 'A2'
17
+ end
18
+
19
+ wb.add_worksheet(:name => 'Next Sheet') do |sheet|
20
+ sheet.add_row ['hello!']
21
+ end
22
+
23
+ p.serialize 'hyperlinks.xlsx'
@@ -1,4 +1,4 @@
1
- $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
1
+ $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../../lib"
2
2
 
3
3
  require 'axlsx'
4
4
 
@@ -54,7 +54,7 @@ Axlsx::Package.new do |p|
54
54
  chart.start_at 7, 16
55
55
  chart.end_at 12, 31
56
56
  end
57
- sheet.merged_cells.concat ["B4:C4","E4:F4","B11:C11","E11:F11","B2:F2"]
57
+ %w(B4:C4 E4:F4 B11:C11 E11:F11 B2:F2).each { |range| sheet.merge_cells(range) }
58
58
  sheet.column_widths 2, nil, nil, 2, nil, nil, 2
59
59
  end
60
60
  end
@@ -134,15 +134,15 @@ module Axlsx
134
134
 
135
135
  # Sets the template property of your app.xml file
136
136
  def template=(v) Axlsx::validate_string v; @template = v; end
137
- alias :Template :template
137
+ alias :Template= :template=
138
138
 
139
139
  # Sets the manager property of your app.xml file
140
140
  def manager=(v) Axlsx::validate_string v; @manager = v; end
141
- alias :Manager :manager
141
+ alias :Manager= :manager=
142
142
 
143
143
  # Sets the company property of your app.xml file
144
144
  def company=(v) Axlsx::validate_string v; @company = v; end
145
- alias :Company :company
145
+ alias :Company= :company=
146
146
  # Sets the pages property of your app.xml file
147
147
  def pages=(v) Axlsx::validate_int v; @pages = v; end
148
148
 
@@ -76,7 +76,7 @@ module Axlsx
76
76
  # image rels namespace
77
77
  IMAGE_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"
78
78
 
79
- # image rels namespace
79
+ # hyperlink rels namespace
80
80
  HYPERLINK_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"
81
81
 
82
82
  # comment rels namespace
@@ -43,7 +43,9 @@ module Axlsx
43
43
  def to_ary
44
44
  @list
45
45
  end
46
-
46
+
47
+ alias :to_a :to_ary
48
+
47
49
  # Unlock the list
48
50
  # @return [self]
49
51
  def unlock
@@ -1,5 +1,5 @@
1
1
  # encoding: UTF-8
2
2
  module Axlsx
3
3
  # The current version
4
- VERSION="1.2.0"
4
+ VERSION="1.2.1"
5
5
  end
@@ -27,6 +27,8 @@ require 'axlsx/workbook/worksheet/dimension.rb'
27
27
  require 'axlsx/workbook/worksheet/sheet_data.rb'
28
28
  require 'axlsx/workbook/worksheet/worksheet_drawing.rb'
29
29
  require 'axlsx/workbook/worksheet/worksheet_comments.rb'
30
+ require 'axlsx/workbook/worksheet/worksheet_hyperlink'
31
+ require 'axlsx/workbook/worksheet/worksheet_hyperlinks'
30
32
  require 'axlsx/workbook/worksheet/worksheet.rb'
31
33
  require 'axlsx/workbook/shared_strings_table.rb'
32
34
  require 'axlsx/workbook/defined_name.rb'
@@ -343,7 +343,7 @@ module Axlsx
343
343
  private
344
344
 
345
345
  def font_size
346
- sz || @styles.fonts[@styles.cellXfs[style].fontId].sz
346
+ sz || @styles.fonts[@styles.cellXfs[style].fontId].sz || @styles.fonts[0].sz
347
347
  end
348
348
 
349
349
  # Utility method for setting inline style attributes
@@ -70,7 +70,13 @@ module Axlsx
70
70
  def tables
71
71
  @tables ||= Tables.new self
72
72
  end
73
-
73
+
74
+ # A typed collection of hyperlinks associated with this worksheet
75
+ # @return [WorksheetHyperlinks]
76
+ def hyperlinks
77
+ @hyperlinks ||= WorksheetHyperlinks.new self
78
+ end
79
+
74
80
  # The a shortcut to the worksheet_comments list of comments
75
81
  # @return [Array|SimpleTypedList]
76
82
  def comments
@@ -391,6 +397,14 @@ module Axlsx
391
397
  data_validations << dv
392
398
  end
393
399
 
400
+ # Adds a new hyperlink to the worksheet
401
+ # @param [Hash] options for the hyperlink
402
+ # @see WorksheetHyperlink for a list of options
403
+ # @return [WorksheetHyperlink]
404
+ def add_hyperlink(options={})
405
+ hyperlinks.add(options)
406
+ end
407
+
394
408
  # Adds a chart to this worksheets drawing. This is the recommended way to create charts for your worksheet. This method wraps the complexity of dealing with ooxml drawing, anchors, markers graphic frames chart objects and all the other dirty details.
395
409
  # @param [Class] chart_type
396
410
  # @option options [Array] start_at
@@ -490,12 +504,21 @@ module Axlsx
490
504
  # @return [Relationships]
491
505
  def relationships
492
506
  r = Relationships.new
493
- r + [tables.relationships,
494
- worksheet_comments.relationships,
507
+ r + [tables.relationships,
508
+ worksheet_comments.relationships,
509
+ hyperlinks.relationships,
495
510
  worksheet_drawing.relationship].flatten.compact || []
496
511
  r
497
512
  end
498
513
 
514
+ # identifies the index of an object withing the collections used in generating relationships for the worksheet
515
+ # @param [Any] object the object to search for
516
+ # @return [Integer] The index of the object
517
+ def relationships_index_of(object)
518
+ objects = [tables.to_a, worksheet_comments.comments.to_a, hyperlinks.to_a, worksheet_drawing.drawing].flatten.compact || []
519
+ objects.index(object)
520
+ end
521
+
499
522
  # Returns the cell or cells defined using excel style A1:B3 references.
500
523
  # @param [String|Integer] cell_def the string defining the cell or range of cells, or the rownumber
501
524
  # @return [Cell, Array]
@@ -548,7 +571,7 @@ module Axlsx
548
571
  [sheet_pr, dimension, sheet_view, column_info,
549
572
  sheet_data, @sheet_protection, protected_ranges,
550
573
  auto_filter, merged_cells, conditional_formattings,
551
- data_validations, print_options, page_margins,
574
+ data_validations, hyperlinks, print_options, page_margins,
552
575
  page_setup, worksheet_drawing, worksheet_comments,
553
576
  tables]
554
577
  end
@@ -0,0 +1,101 @@
1
+ module Axlsx
2
+
3
+ # A worksheet hyperlink object. Note that this is not the same as a drawing hyperlink object.
4
+ class WorksheetHyperlink
5
+
6
+ # Creates a new hyperlink object.
7
+ # @note the preferred way to add hyperlinks to your worksheet is the Worksheet#add_hyperlink method
8
+ # @param [Worksheet] worksheet the Worksheet that owns this hyperlink
9
+ # @param [Hash] options options to use when creating this hyperlink
10
+ # @option [String] display Display string, if different from string in string table. This is a property on the hyperlink object, but does not need to appear in the spreadsheet application UI.
11
+ # @option [String] location Location within target. If target is a workbook (or this workbook) this shall refer to a sheet and cell or a defined name. Can also be an HTML anchor if target is HTML file.
12
+ # @option [String] tooltip The tip to display when the user positions the mouse cursor over this hyperlink
13
+ # @option [Symbol] target This is :external by default. If you set it to anything else, the location is interpreted to be the current workbook.
14
+ # @option [String|Cell] ref The location of this hyperlink in the worksheet
15
+ def initialize(worksheet, options={})
16
+ DataTypeValidator.validate "Hyperlink.worksheet", [Worksheet], worksheet
17
+ @worksheet = worksheet
18
+ @target = :external
19
+ options.each do |o|
20
+ self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
21
+ end
22
+ yield self if block_given?
23
+ end
24
+
25
+ # String attributes for this object
26
+ STRING_ATTRIBUTES = %w(display location tooltip)
27
+
28
+ #Cell location of hyperlink on worksheet.
29
+ # @return [String]
30
+ attr_reader :ref
31
+
32
+ # Sets the target for this hyperlink. Anything other than :external instructs the library to treat the location as an in-workbook reference.
33
+ # @param [Symbol] target
34
+ def target=(target)
35
+ @target = target
36
+ end
37
+
38
+ # Sets the cell location of this hyperlink in the worksheet
39
+ # @param [String|Cell] cell_reference The string reference or cell that defines where this hyperlink shows in the worksheet.
40
+ def ref=(cell_reference)
41
+ cell_reference = cell_reference.r if cell_reference.is_a?(Cell)
42
+
43
+ Axlsx::validate_string cell_reference
44
+ @ref = cell_reference
45
+ end
46
+
47
+ # Dynamically create string attribute accessors
48
+ STRING_ATTRIBUTES.each do |attr|
49
+ class_eval %{
50
+ # The #{attr} attribute reader
51
+ # @return [String]
52
+ attr_reader :#{attr}
53
+
54
+ # The #{attr} writer
55
+ # @param [String] value The value to assign to #{attr}
56
+ # @return [String]
57
+ def #{attr}=(value)
58
+ Axlsx::validate_string(value)
59
+ @#{attr}= value
60
+ end
61
+ }
62
+ end
63
+
64
+ # The relationship required by this hyperlink when the taget is :external
65
+ # @return [Relationship]
66
+ def relationship
67
+ return unless @target == :external
68
+ Relationship.new HYPERLINK_R, location, :target_mode => :External
69
+ end
70
+
71
+ # The id of the relationship for this object
72
+ # @return [String]
73
+ def id
74
+ return unless @target == :external
75
+ "rId#{(@worksheet.relationships_index_of(self)+1)}"
76
+ end
77
+
78
+ # Seralize the object
79
+ # @param [String] str
80
+ # @return [String]
81
+ def to_xml_string(str='')
82
+ str << '<hyperlink '
83
+ serialization_values.map { |key, value| str << key.to_s << '="' << value.to_s << '" ' }
84
+ str << '/>'
85
+ end
86
+
87
+ # The values to be used in serialization based on the target.
88
+ # location should only be specified for non-external targets.
89
+ # r:id should only be specified for external targets.
90
+ # @return [Hash]
91
+ def serialization_values
92
+ h = instance_values.reject { |key, value| !%w(display ref tooltip).include?(key) }
93
+ if @target == :external
94
+ h['r:id'] = id
95
+ else
96
+ h['location'] = location
97
+ end
98
+ h
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,35 @@
1
+ module Axlsx
2
+ #A collection of hyperlink objects for a worksheet
3
+ class WorksheetHyperlinks < SimpleTypedList
4
+
5
+ # Creates a new Hyperlinks collection
6
+ # @param [Worksheet] worksheet the worksheet that owns these hyperlinks
7
+ def initialize(worksheet)
8
+ DataTypeValidator.validate "Hyperlinks.worksheet", [Worksheet], worksheet
9
+ @worksheet = worksheet
10
+ super WorksheetHyperlink
11
+ end
12
+
13
+ # Creates and adds a new hyperlink based on the options provided
14
+ # @see WorksheetHyperlink#initialize
15
+ # @return [WorksheetHyperlink]
16
+ def add(options)
17
+ @list << WorksheetHyperlink.new(@worksheet, options)
18
+ @list.last
19
+ end
20
+
21
+ def relationships
22
+ return [] if empty?
23
+ map { |hyperlink| hyperlink.relationship }
24
+ end
25
+
26
+ # seralize the collection of hyperlinks
27
+ # @return [String]
28
+ def to_xml_string(str='')
29
+ return if empty?
30
+ str << '<hyperlinks>'
31
+ @list.each { |hyperlink| hyperlink.to_xml_string(str) }
32
+ str << '</hyperlinks>'
33
+ end
34
+ end
35
+ end
@@ -7,6 +7,7 @@ class TestPackage < Test::Unit::TestCase
7
7
  ws = @package.workbook.add_worksheet
8
8
  ws.add_row ['Can', 'we', 'build it?']
9
9
  ws.add_row ['Yes!', 'We', 'can!']
10
+ ws.add_hyperlink :ref => ws.rows.first.cells.last, :location => 'https://github.com/randym'
10
11
  ws.workbook.add_defined_name("#{ws.name}!A1:C2", :name => '_xlnm.Print_Titles', :hidden => true)
11
12
  ws.protect_range('A1:C1')
12
13
  ws.protect_range(ws.rows.last.cells)
@@ -268,6 +268,22 @@ class TestCell < Test::Unit::TestCase
268
268
 
269
269
  end
270
270
 
271
+ def test_font_size_with_custom_style_and_no_sz
272
+ @c.style = @c.row.worksheet.workbook.styles.add_style :bg_color => 'FF00FF'
273
+ sz = @c.send(:font_size)
274
+ assert_equal(sz, @c.row.worksheet.workbook.styles.fonts.first.sz)
275
+ end
276
+
277
+ def test_font_size_with_custom_sz
278
+ @c.style = @c.row.worksheet.workbook.styles.add_style :sz => 52
279
+ sz = @c.send(:font_size)
280
+ assert_equal(sz, 52)
281
+ end
282
+
283
+ def test_cell_with_sz
284
+ @c.sz = 25
285
+ assert_equal(25, @c.send(:font_size))
286
+ end
271
287
  def test_to_xml
272
288
  # TODO This could use some much more stringent testing related to the xml content generated!
273
289
  @ws.add_row [Time.now, Date.today, true, 1, 1.0, "text", "=sum(A1:A2)"]
@@ -0,0 +1,64 @@
1
+ require 'tc_helper.rb'
2
+
3
+ class TestWorksheetHyperlink < Test::Unit::TestCase
4
+ def setup
5
+ p = Axlsx::Package.new
6
+ wb = p.workbook
7
+ @ws = wb.add_worksheet
8
+ @options = { :location => 'https://github.com/randym/axlsx', :tooltip => 'axlsx', :ref => 'A1', :display => 'AXSLX', :target => :internal }
9
+ @a = @ws.add_hyperlink @options
10
+ end
11
+
12
+ def test_initailize
13
+ assert_raise(ArgumentError) { Axlsx::WorksheetHyperlink.new }
14
+ end
15
+
16
+ def test_location
17
+ assert_equal(@options[:location], @a.location)
18
+ end
19
+
20
+ def test_tooltip
21
+ assert_equal(@options[:tooltip], @a.tooltip)
22
+ end
23
+
24
+ def test_target
25
+ assert_equal(@options[:target], @a.instance_values['target'])
26
+ end
27
+
28
+ def test_display
29
+ assert_equal(@options[:display], @a.display)
30
+ end
31
+ def test_ref
32
+ assert_equal(@options[:ref], @a.ref)
33
+ end
34
+
35
+ def test_id
36
+ @a.target = :external
37
+
38
+ assert_equal("rId1", @a.id)
39
+ @a.target = :internal
40
+ assert_equal(nil, @a.id)
41
+ end
42
+
43
+
44
+ def test_to_xml_string_with_non_external
45
+ doc = Nokogiri::XML(@ws.to_xml_string)
46
+ assert_equal(doc.xpath("//xmlns:hyperlink[@ref='#{@a.ref}']").size, 1)
47
+ assert_equal(doc.xpath("//xmlns:hyperlink[@tooltip='#{@a.tooltip}']").size, 1)
48
+ assert_equal(doc.xpath("//xmlns:hyperlink[@location='#{@a.location}']").size, 1)
49
+ assert_equal(doc.xpath("//xmlns:hyperlink[@display='#{@a.display}']").size, 1)
50
+ assert_equal(doc.xpath("//xmlns:hyperlink[@r:id='#{@a.id}']").size, 0)
51
+ end
52
+
53
+ def test_to_xml_stirng_with_external
54
+ @a.target = :external
55
+ doc = Nokogiri::XML(@ws.to_xml_string)
56
+ assert_equal(doc.xpath("//xmlns:hyperlink[@ref='#{@a.ref}']").size, 1)
57
+ assert_equal(doc.xpath("//xmlns:hyperlink[@tooltip='#{@a.tooltip}']").size, 1)
58
+ assert_equal(doc.xpath("//xmlns:hyperlink[@display='#{@a.display}']").size, 1)
59
+ assert_equal(doc.xpath("//xmlns:hyperlink[@location='#{@a.location}']").size, 0)
60
+ assert_equal(doc.xpath("//xmlns:hyperlink[@r:id='#{@a.id}']").size, 1)
61
+ end
62
+ end
63
+
64
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: axlsx
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.2.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-05 00:00:00.000000000 Z
12
+ date: 2012-08-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: nokogiri
@@ -226,6 +226,8 @@ files:
226
226
  - lib/axlsx/workbook/worksheet/worksheet.rb
227
227
  - lib/axlsx/workbook/worksheet/worksheet_comments.rb
228
228
  - lib/axlsx/workbook/worksheet/worksheet_drawing.rb
229
+ - lib/axlsx/workbook/worksheet/worksheet_hyperlink.rb
230
+ - lib/axlsx/workbook/worksheet/worksheet_hyperlinks.rb
229
231
  - lib/axlsx.rb
230
232
  - lib/schema/dc.xsd
231
233
  - lib/schema/dcmitype.xsd
@@ -275,6 +277,7 @@ files:
275
277
  - examples/example_streamed.xlsx
276
278
  - examples/extractive.pdf
277
279
  - examples/extractive.rb
280
+ - examples/hyperlinks.rb
278
281
  - examples/image1.gif
279
282
  - examples/image1.jpeg
280
283
  - examples/image1.jpg
@@ -285,6 +288,7 @@ files:
285
288
  - examples/shared_strings_example.xlsx
286
289
  - examples/sheet_protection.rb
287
290
  - examples/sheet_view.rb
291
+ - examples/skydrive/axlsx.xlsx
288
292
  - examples/skydrive/real_example.rb
289
293
  - examples/two_cell_anchor_image.rb
290
294
  - LICENSE
@@ -385,6 +389,7 @@ files:
385
389
  - test/workbook/worksheet/tc_sheet_protection.rb
386
390
  - test/workbook/worksheet/tc_sheet_view.rb
387
391
  - test/workbook/worksheet/tc_worksheet.rb
392
+ - test/workbook/worksheet/tc_worksheet_hyperlink.rb
388
393
  homepage: https://github.com/randym/axlsx
389
394
  licenses: []
390
395
  post_install_message:
@@ -405,7 +410,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
405
410
  version: '0'
406
411
  segments:
407
412
  - 0
408
- hash: 2125383540867602531
413
+ hash: 1432590865513954049
409
414
  requirements: []
410
415
  rubyforge_project:
411
416
  rubygems_version: 1.8.24
@@ -506,4 +511,5 @@ test_files:
506
511
  - test/workbook/worksheet/tc_sheet_protection.rb
507
512
  - test/workbook/worksheet/tc_sheet_view.rb
508
513
  - test/workbook/worksheet/tc_worksheet.rb
514
+ - test/workbook/worksheet/tc_worksheet_hyperlink.rb
509
515
  has_rdoc: axlsx