axlsx 1.3.6 → 2.0.1

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.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts_guide +19 -0
  3. data/CHANGELOG.md +8 -0
  4. data/README.md +54 -79
  5. data/Rakefile +0 -5
  6. data/examples/2010_comments.rb +17 -0
  7. data/examples/anchor_swapping.rb +28 -0
  8. data/examples/example.rb +16 -1
  9. data/examples/pivot_table.rb +2 -0
  10. data/examples/underline.rb +13 -0
  11. data/lib/axlsx/doc_props/core.rb +6 -1
  12. data/lib/axlsx/drawing/axes.rb +7 -3
  13. data/lib/axlsx/drawing/bar_3D_chart.rb +2 -2
  14. data/lib/axlsx/drawing/chart.rb +20 -4
  15. data/lib/axlsx/drawing/drawing.rb +2 -17
  16. data/lib/axlsx/drawing/graphic_frame.rb +3 -8
  17. data/lib/axlsx/drawing/hyperlink.rb +5 -12
  18. data/lib/axlsx/drawing/marker.rb +25 -5
  19. data/lib/axlsx/drawing/one_cell_anchor.rb +9 -0
  20. data/lib/axlsx/drawing/pic.rb +17 -23
  21. data/lib/axlsx/drawing/two_cell_anchor.rb +7 -27
  22. data/lib/axlsx/package.rb +36 -16
  23. data/lib/axlsx/rels/relationship.rb +73 -8
  24. data/lib/axlsx/rels/relationships.rb +8 -1
  25. data/lib/axlsx/stylesheet/color.rb +1 -1
  26. data/lib/axlsx/stylesheet/num_fmt.rb +2 -2
  27. data/lib/axlsx/stylesheet/styles.rb +5 -3
  28. data/lib/axlsx/util/serialized_attributes.rb +11 -8
  29. data/lib/axlsx/util/simple_typed_list.rb +34 -13
  30. data/lib/axlsx/util/validators.rb +7 -0
  31. data/lib/axlsx/version.rb +1 -1
  32. data/lib/axlsx/workbook/defined_name.rb +1 -1
  33. data/lib/axlsx/workbook/shared_strings_table.rb +12 -3
  34. data/lib/axlsx/workbook/workbook.rb +31 -8
  35. data/lib/axlsx/workbook/worksheet/break.rb +37 -0
  36. data/lib/axlsx/workbook/worksheet/cell.rb +5 -5
  37. data/lib/axlsx/workbook/worksheet/cell_serializer.rb +1 -1
  38. data/lib/axlsx/workbook/worksheet/col_breaks.rb +35 -0
  39. data/lib/axlsx/workbook/worksheet/comment.rb +6 -5
  40. data/lib/axlsx/workbook/worksheet/comments.rb +3 -3
  41. data/lib/axlsx/workbook/worksheet/conditional_formatting_rule.rb +1 -1
  42. data/lib/axlsx/workbook/worksheet/date_time_converter.rb +6 -5
  43. data/lib/axlsx/workbook/worksheet/pivot_table.rb +32 -18
  44. data/lib/axlsx/workbook/worksheet/pivot_table_cache_definition.rb +4 -3
  45. data/lib/axlsx/workbook/worksheet/pivot_tables.rb +1 -1
  46. data/lib/axlsx/workbook/worksheet/row.rb +1 -1
  47. data/lib/axlsx/workbook/worksheet/row_breaks.rb +33 -0
  48. data/lib/axlsx/workbook/worksheet/table.rb +3 -2
  49. data/lib/axlsx/workbook/worksheet/tables.rb +1 -1
  50. data/lib/axlsx/workbook/worksheet/worksheet.rb +61 -26
  51. data/lib/axlsx/workbook/worksheet/worksheet_comments.rb +6 -5
  52. data/lib/axlsx/workbook/worksheet/worksheet_drawing.rb +3 -9
  53. data/lib/axlsx/workbook/worksheet/worksheet_hyperlink.rb +5 -10
  54. data/lib/axlsx.rb +10 -2
  55. data/lib/schema/sml.xsd +4 -0
  56. data/test/axlsx.qcachegrind +2226 -0
  57. data/test/doc_props/tc_core.rb +7 -0
  58. data/test/drawing/tc_axes.rb +8 -0
  59. data/test/drawing/tc_bar_3D_chart.rb +6 -0
  60. data/test/drawing/tc_chart.rb +13 -0
  61. data/test/drawing/tc_drawing.rb +0 -5
  62. data/test/drawing/tc_graphic_frame.rb +4 -7
  63. data/test/drawing/tc_hyperlink.rb +0 -4
  64. data/test/drawing/tc_pic.rb +14 -3
  65. data/test/drawing/tc_two_cell_anchor.rb +3 -3
  66. data/test/profile.rb +7 -3
  67. data/test/rels/tc_relationship.rb +29 -11
  68. data/test/rels/tc_relationships.rb +12 -1
  69. data/test/stylesheet/tc_color.rb +6 -0
  70. data/test/stylesheet/tc_styles.rb +2 -2
  71. data/test/tc_helper.rb +1 -0
  72. data/test/tc_package.rb +31 -1
  73. data/test/util/tc_serialized_attributes.rb +19 -0
  74. data/test/workbook/tc_shared_strings_table.rb +6 -0
  75. data/test/workbook/tc_workbook.rb +23 -1
  76. data/test/workbook/worksheet/tc_break.rb +49 -0
  77. data/test/workbook/worksheet/tc_comment.rb +17 -6
  78. data/test/workbook/worksheet/tc_conditional_formatting.rb +2 -2
  79. data/test/workbook/worksheet/tc_date_time_converter.rb +3 -11
  80. data/test/workbook/worksheet/tc_pivot_table.rb +40 -22
  81. data/test/workbook/worksheet/tc_pivot_table_cache_definition.rb +9 -1
  82. data/test/workbook/worksheet/tc_sheet_view.rb +39 -39
  83. data/test/workbook/worksheet/tc_table.rb +2 -2
  84. data/test/workbook/worksheet/tc_worksheet.rb +39 -7
  85. data/test/workbook/worksheet/tc_worksheet_hyperlink.rb +2 -11
  86. metadata +39 -11
  87. data/test/example.xlsx +0 -0
@@ -37,6 +37,8 @@ module Axlsx
37
37
  @page_setup = PageSetup.new options[:page_setup] if options[:page_setup]
38
38
  @print_options = PrintOptions.new options[:print_options] if options[:print_options]
39
39
  @header_footer = HeaderFooter.new options[:header_footer] if options[:header_footer]
40
+ @row_breaks = RowBreaks.new
41
+ @col_breaks = ColBreaks.new
40
42
  end
41
43
 
42
44
  # The name of the worksheet
@@ -94,6 +96,22 @@ module Axlsx
94
96
  @pivot_tables ||= PivotTables.new self
95
97
  end
96
98
 
99
+ # A collection of column breaks added to this worksheet
100
+ # @note Please do not use this directly. Instead use
101
+ # add_page_break
102
+ # @see Worksheet#add_page_break
103
+ def col_breaks
104
+ @col_breaks ||= ColBreaks.new
105
+ end
106
+
107
+ # A collection of row breaks added to this worksheet
108
+ # @note Please do not use this directly. Instead use
109
+ # add_page_break
110
+ # @see Worksheet#add_page_break
111
+ def row_breaks
112
+ @row_breaks ||= RowBreaks.new
113
+ end
114
+
97
115
  # A typed collection of hyperlinks associated with this worksheet
98
116
  # @return [WorksheetHyperlinks]
99
117
  def hyperlinks
@@ -114,14 +132,19 @@ module Axlsx
114
132
  @rows ||= SimpleTypedList.new Row
115
133
  end
116
134
 
117
- # returns the sheet data as columnw
118
- def cols
119
- @rows.transpose
135
+ # returns the sheet data as columns
136
+ # If you pass a block, it will be evaluated whenever a row does not have a
137
+ # cell at a specific index. The block will be called with the row and column
138
+ # index in the missing cell was found.
139
+ # @example
140
+ # cols { |row_index, column_index| p "warn - row #{row_index} is does not have a cell at #{column_index}
141
+ def cols(&block)
142
+ @rows.transpose(&block)
120
143
  end
121
144
 
122
- # An range that excel will apply an autfilter to "A1:B3"
145
+ # An range that excel will apply an auto-filter to "A1:B3"
123
146
  # This will turn filtering on for the cells in the range.
124
- # The first row is considered the header, while subsequent rows are considerd to be data.
147
+ # The first row is considered the header, while subsequent rows are considered to be data.
125
148
  # @return String
126
149
  def auto_filter
127
150
  @auto_filter ||= AutoFilter.new self
@@ -327,6 +350,10 @@ module Axlsx
327
350
  auto_filter.range = v
328
351
  end
329
352
 
353
+ # Accessor for controlling whether leading and trailing spaces in cells are
354
+ # preserved or ignored. The default is to preserve spaces.
355
+ attr_accessor :preserve_spaces
356
+
330
357
  # The part name of this worksheet
331
358
  # @return [String]
332
359
  def pn
@@ -339,10 +366,11 @@ module Axlsx
339
366
  "#{WORKSHEET_RELS_PN % (index+1)}"
340
367
  end
341
368
 
342
- # The relationship Id of thiw worksheet
369
+ # The relationship id of this worksheet.
343
370
  # @return [String]
371
+ # @see Relationship#Id
344
372
  def rId
345
- "rId#{index+1}"
373
+ @workbook.relationships.for(self).Id
346
374
  end
347
375
 
348
376
  # The index of this worksheet in the owning Workbook's worksheets list.
@@ -488,6 +516,24 @@ module Axlsx
488
516
  image
489
517
  end
490
518
 
519
+ # Adds a page break (row break) to the worksheet
520
+ # @param cell A Cell object or excel style string reference indicating where the break
521
+ # should be added to the sheet.
522
+ # @example
523
+ # ws.add_page_break("A4")
524
+ def add_page_break(cell)
525
+ DataTypeValidator.validate "Worksheet#add_page_break cell", [String, Cell], cell
526
+ column_index, row_index = if cell.is_a?(String)
527
+ Axlsx.name_to_indices(cell)
528
+ else
529
+ cell.pos
530
+ end
531
+ if column_index > 0
532
+ col_breaks.add_break(:id => column_index)
533
+ end
534
+ row_breaks.add_break(:id => row_index)
535
+ end
536
+
491
537
  # This is a helper method that Lets you specify a fixed width for multiple columns in a worksheet in one go.
492
538
  # Axlsx is sparse, so if you have not set data for a column, you cannot set the width.
493
539
  # Setting a fixed column width to nil will revert the behaviour back to calculating the width for you on the next call to add_row.
@@ -542,15 +588,7 @@ module Axlsx
542
588
  item.to_xml_string(str) if item
543
589
  end
544
590
  str << '</worksheet>'
545
- sanitize(str)
546
- end
547
-
548
- # returns the provided string with all invalid control charaters
549
- # removed.
550
- # @param [String] str The sting to process
551
- # @return [String]
552
- def sanitize(str)
553
- str.gsub(CONTROL_CHAR_REGEX, '')
591
+ Axlsx::sanitize(str)
554
592
  end
555
593
 
556
594
  # The worksheet relationships. This is managed automatically by the worksheet
@@ -565,14 +603,6 @@ module Axlsx
565
603
  r
566
604
  end
567
605
 
568
- # identifies the index of an object withing the collections used in generating relationships for the worksheet
569
- # @param [Any] object the object to search for
570
- # @return [Integer] The index of the object
571
- def relationships_index_of(object)
572
- objects = [tables.to_a, worksheet_comments.comments.to_a, hyperlinks.to_a, worksheet_drawing.drawing].flatten.compact || []
573
- objects.index(object)
574
- end
575
-
576
606
  # Returns the cell or cells defined using excel style A1:B3 references.
577
607
  # @param [String|Integer] cell_def the string defining the cell or range of cells, or the rownumber
578
608
  # @return [Cell, Array]
@@ -629,6 +659,11 @@ module Axlsx
629
659
  end
630
660
 
631
661
  private
662
+
663
+ def xml_space
664
+ workbook.xml_space
665
+ end
666
+
632
667
  def outline(collection, range, level = 1, collapsed = true)
633
668
  range.each do |index|
634
669
  unless (item = collection[index]).nil?
@@ -653,7 +688,7 @@ module Axlsx
653
688
  sheet_data, sheet_calc_pr, @sheet_protection, protected_ranges,
654
689
  auto_filter, merged_cells, conditional_formattings,
655
690
  data_validations, hyperlinks, print_options, page_margins,
656
- page_setup, header_footer, worksheet_drawing, worksheet_comments,
691
+ page_setup, header_footer, row_breaks, col_breaks, worksheet_drawing, worksheet_comments,
657
692
  tables]
658
693
  end
659
694
 
@@ -699,7 +734,7 @@ module Axlsx
699
734
  # Helper method for parsingout the root node for worksheet
700
735
  # @return [String]
701
736
  def worksheet_node
702
- "<worksheet xmlns=\"%s\" xmlns:r=\"%s\">" % [XML_NS, XML_NS_R]
737
+ "<worksheet xmlns=\"%s\" xmlns:r=\"%s\" xml:space=\"#{xml_space}\">" % [XML_NS, XML_NS_R]
703
738
  end
704
739
 
705
740
  def sheet_data
@@ -40,10 +40,11 @@ module Axlsx
40
40
  !comments.empty?
41
41
  end
42
42
 
43
- # The index in the worksheet's relationships for the VML drawing that will render the comments
44
- # @return [Integer]
45
- def index
46
- worksheet.relationships.index { |r| r.Type == VML_DRAWING_R } + 1
43
+ # The relationship id of the VML drawing that will render the comments.
44
+ # @see Relationship#Id
45
+ # @return [String]
46
+ def drawing_rId
47
+ comments.relationships.find{ |r| r.Type == VML_DRAWING_R }.Id
47
48
  end
48
49
 
49
50
  # Seraalize the object
@@ -51,7 +52,7 @@ module Axlsx
51
52
  # @return [String]
52
53
  def to_xml_string(str = '')
53
54
  return unless has_comments?
54
- str << "<legacyDrawing r:id='rId#{index}' />"
55
+ str << "<legacyDrawing r:id='#{drawing_rId}' />"
55
56
  end
56
57
  end
57
58
  end
@@ -41,24 +41,18 @@ module Axlsx
41
41
  @drawing.is_a? Drawing
42
42
  end
43
43
 
44
- # The relationship required by this object
44
+ # The relationship instance for this drawing.
45
45
  # @return [Relationship]
46
46
  def relationship
47
47
  return unless has_drawing?
48
- Relationship.new(DRAWING_R, "../#{drawing.pn}")
49
- end
50
-
51
- # returns the index of the worksheet releationship that defines this drawing.
52
- # @return [Integer]
53
- def index
54
- worksheet.relationships.index{ |r| r.Type == DRAWING_R } +1
48
+ Relationship.new(self, DRAWING_R, "../#{drawing.pn}")
55
49
  end
56
50
 
57
51
  # Serialize the drawing for the worksheet
58
52
  # @param [String] str
59
53
  def to_xml_string(str = '')
60
54
  return unless has_drawing?
61
- str << "<drawing r:id='rId#{index}'/>"
55
+ str << "<drawing r:id='#{relationship.Id}'/>"
62
56
  end
63
57
  end
64
58
  end
@@ -45,18 +45,13 @@ module Axlsx
45
45
  @ref = cell_reference
46
46
  end
47
47
 
48
- # The relationship required by this hyperlink when the taget is :external
48
+ # The relationship instance for this hyperlink.
49
+ # A relationship is only required if `@target` is `:external`. If not, this method will simply return `nil`.
50
+ # @see #target=
49
51
  # @return [Relationship]
50
52
  def relationship
51
53
  return unless @target == :external
52
- Relationship.new HYPERLINK_R, location, :target_mode => :External
53
- end
54
-
55
- # The id of the relationship for this object
56
- # @return [String]
57
- def id
58
- return unless @target == :external
59
- "rId#{(@worksheet.relationships_index_of(self)+1)}"
54
+ Relationship.new(self, HYPERLINK_R, location, :target_mode => :External)
60
55
  end
61
56
 
62
57
  # Seralize the object
@@ -73,7 +68,7 @@ module Axlsx
73
68
  # r:id should only be specified for external targets.
74
69
  # @return [Hash]
75
70
  def location_or_id
76
- @target == :external ? { :"r:id" => id } : { :location => Axlsx::coder.encode(location) }
71
+ @target == :external ? { :"r:id" => relationship.Id } : { :location => Axlsx::coder.encode(location) }
77
72
  end
78
73
  end
79
74
  end
data/lib/axlsx.rb CHANGED
@@ -23,7 +23,7 @@ require 'axlsx/workbook/workbook.rb'
23
23
  require 'axlsx/package.rb'
24
24
  #required gems
25
25
  require 'nokogiri'
26
- require 'zip/zip'
26
+ require 'zip'
27
27
 
28
28
  #core dependencies
29
29
  require 'bigdecimal'
@@ -127,8 +127,16 @@ module Axlsx
127
127
  s.gsub(/_(.)/){ $1.upcase }
128
128
  end
129
129
 
130
+ # returns the provided string with all invalid control charaters
131
+ # removed.
132
+ # @param [String] str The sting to process
133
+ # @return [String]
134
+ def self.sanitize(str)
135
+ str.gsub(CONTROL_CHAR_REGEX, '')
136
+ end
137
+
130
138
 
131
- # Instructs the serializer to not try to escape cell value input.
139
+ # Instructs the serializer to not try to escape cell value input.
132
140
  # This will give you a huge speed bonus, but if you content has <, > or other xml character data
133
141
  # the workbook will be invalid and excel will complain.
134
142
  def self.trust_input
data/lib/schema/sml.xsd CHANGED
@@ -13,6 +13,8 @@
13
13
  <xsd:import
14
14
  namespace="http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"
15
15
  schemaLocation="dml-spreadsheetDrawing.xsd"/>
16
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="xml.xsd"/>
17
+
16
18
  <xsd:complexType name="CT_AutoFilter">
17
19
  <xsd:sequence>
18
20
  <xsd:element name="filterColumn" minOccurs="0" maxOccurs="unbounded" type="CT_FilterColumn"/>
@@ -1797,6 +1799,7 @@
1797
1799
  </xsd:sequence>
1798
1800
  <xsd:attribute name="count" type="xsd:unsignedInt" use="optional"/>
1799
1801
  <xsd:attribute name="uniqueCount" type="xsd:unsignedInt" use="optional"/>
1802
+ <xsd:attribute ref="xml:space"/>
1800
1803
  </xsd:complexType>
1801
1804
  <xsd:simpleType name="ST_PhoneticType">
1802
1805
  <xsd:restriction base="xsd:string">
@@ -2213,6 +2216,7 @@
2213
2216
  <xsd:element name="tableParts" type="CT_TableParts" minOccurs="0" maxOccurs="1"/>
2214
2217
  <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
2215
2218
  </xsd:sequence>
2219
+ <xsd:attribute ref="xml:space"/>
2216
2220
  </xsd:complexType>
2217
2221
  <xsd:complexType name="CT_SheetData">
2218
2222
  <xsd:sequence>