caxlsx 3.0.1 → 3.0.2

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.
@@ -1,59 +1,45 @@
1
- require 'axlsx'
1
+ require 'axlsx'
2
2
 
3
- ###############################
4
- # Function to output results data row to summary spreadsheet
5
- def outputRow (sid, type)
3
+ p = Axlsx::Package.new
4
+ wb = p.workbook
6
5
 
7
- $sumSheet.add_row [ sid, type, "1", "2", "3", "4", "5" ], :style => $black_cell
6
+ # Each style only needs to be declared once in the workbook.
7
+ s = wb.styles
8
+ title_cell = s.add_style sz: 14, alignment: { horizontal: :center }
9
+ black_cell = s.add_style sz: 10, alignment: { horizontal: :center }
10
+ blue_link = s.add_style fg_color: '0000FF'
11
+
12
+ # Create summary sheet
13
+ sum_sheet = wb.add_worksheet name: 'Summary'
14
+ sum_sheet.add_row ['Test Results'], sz: 16
15
+ sum_sheet.add_row
16
+ sum_sheet.add_row
17
+ sum_sheet.add_row ['Note: Blue cells below are links to the Log sheet'], sz: 10
18
+ sum_sheet.add_row
19
+ sum_sheet.add_row ['ID', 'Type', 'Match', 'Mismatch', 'Diffs', 'Errors', 'Result'], style: title_cell
20
+
21
+ sum_sheet.column_widths 10, 10, 1 0, 11, 10, 10, 10
22
+
23
+ # Starting data row in summary spreadsheet (after header info)
24
+ current_row = 7
25
+
26
+ # Create Log Sheet
27
+ log_sheet = wb.add_worksheet name: 'Log'
28
+ log_sheet.column_widths 10
29
+ log_sheet.add_row ['Log Detail'], sz: 16
30
+ log_sheet.add_row
31
+
32
+ # Add rows to summary sheet
33
+ (1..10).each do |sid|
34
+ sum_sheet.add_row [sid, 'test', '1', '2', '3', '4', '5'], style: black_cell
8
35
 
9
36
  if sid.odd?
10
- link = "A#{$curRow}"
11
- puts "outputRow: sid: #{sid}, link: #{link}"
12
- # Setting the style for the link will apply the xf that we created in the Main Program block
13
- $sumSheet[link].style = $blue_link
14
- $sumSheet.add_hyperlink :location => "'Log'!A#{$curRow}", :target => :sheet, :ref => link
37
+ link = "A#{current_row}"
38
+ sum_sheet[link].style = blue_link
39
+ sum_sheet.add_hyperlink location: "'Log'!A#{current_row}", target: :sheet, ref: link
15
40
  end
16
- $curRow += 1
17
- end
18
41
 
19
- ##############################
20
- # Main Program
42
+ current_row += 1
43
+ end
21
44
 
22
- $package = Axlsx::Package.new
23
- $workbook = $package.workbook
24
- ## We want to create our sytles outside of the outputRow method
25
- # Each style only needs to be declared once in the workbook.
26
- $workbook.styles do |s|
27
- $black_cell = s.add_style :sz => 10, :alignment => { :horizontal=> :center }
28
- $blue_link = s.add_style :fg_color => '0000FF'
29
- end
30
-
31
-
32
- # Create summary sheet
33
- $sumSheet = $workbook.add_worksheet(:name => 'Summary')
34
- $sumSheet.add_row ["Test Results"], :sz => 16
35
- $sumSheet.add_row
36
- $sumSheet.add_row
37
- $sumSheet.add_row ["Note: Blue cells below are links to the Log sheet"], :sz => 10
38
- $sumSheet.add_row
39
- $workbook.styles do |s|
40
- black_cell = s.add_style :sz => 14, :alignment => { :horizontal=> :center }
41
- $sumSheet.add_row ["ID","Type","Match","Mismatch","Diffs","Errors","Result"], :style => black_cell
42
- end
43
- $sumSheet.column_widths 10, 10, 10, 11, 10, 10, 10
44
-
45
- # Starting data row in summary spreadsheet (after header info)
46
- $curRow = 7
47
-
48
- # Create Log Sheet
49
- $logSheet = $workbook.add_worksheet(:name => 'Log')
50
- $logSheet.column_widths 10
51
- $logSheet.add_row ['Log Detail'], :sz => 16
52
- $logSheet.add_row
53
-
54
- # Add rows to summary sheet
55
- for i in 1..10 do
56
- outputRow(i, 'test')
57
- end
58
-
59
- $package.serialize 'where_is_my_color.xlsx'
45
+ p.serialize 'where_is_my_color.xlsx'
@@ -21,6 +21,7 @@ examples << :images
21
21
  examples << :format_dates
22
22
  examples << :mbcs
23
23
  examples << :formula
24
+ examples << :escape_formulas
24
25
  examples << :auto_filter
25
26
  examples << :sheet_protection
26
27
  examples << :data_types
@@ -364,6 +365,21 @@ if examples.include? :formula
364
365
  end
365
366
  ##```
366
367
 
368
+ ##Escaping formulas for cells
369
+ #```ruby
370
+ if examples.include? :escape_formulas
371
+ wb.add_worksheet(:name => "Escaping Formulas") do |sheet|
372
+ sheet.add_row [1, 2, 3, "=SUM(A2:C2)"], escape_formulas: true
373
+ sheet.add_row [
374
+ "=IF(2+2=4,4,5)",
375
+ "=IF(13+13=4,4,5)",
376
+ "=IF(99+99=4,4,5)"
377
+ ], escape_formulas: [true, false, true]
378
+ end
379
+ p.serialize("escaped_formulas.xlsx")
380
+ end
381
+ ##```
382
+
367
383
  ##Auto Filter
368
384
 
369
385
  #```ruby
@@ -882,4 +898,3 @@ if examples.include? :tab_color
882
898
  p.serialize 'tab_color.xlsx'
883
899
  end
884
900
  ##```
885
-
@@ -9,8 +9,6 @@ require 'axlsx/util/validators.rb'
9
9
  require 'axlsx/util/accessors.rb'
10
10
  require 'axlsx/util/serialized_attributes'
11
11
  require 'axlsx/util/options_parser'
12
- # to be included with parsable intitites.
13
- #require 'axlsx/util/parser.rb'
14
12
  require 'axlsx/util/mime_type_utils'
15
13
 
16
14
  require 'axlsx/stylesheet/styles.rb'
@@ -1,7 +1,7 @@
1
1
  # encoding: UTF-8
2
2
  module Axlsx
3
3
 
4
- # The BarChart is a three dimentional barchart (who would have guessed?) that you can add to your worksheet.
4
+ # The BarChart is a two dimentional barchart that you can add to your worksheet.
5
5
  # @see Worksheet#add_chart
6
6
  # @see Chart#add_series
7
7
  # @see Package#serialize
@@ -49,7 +49,7 @@ module Axlsx
49
49
  @grouping ||= :clustered
50
50
  end
51
51
 
52
- # The shabe of the bars or columns
52
+ # The shape of the bars or columns
53
53
  # must be one of [:cone, :coneToMax, :box, :cylinder, :pyramid, :pyramidToMax]
54
54
  # @return [Symbol]
55
55
  def shape
@@ -106,7 +106,7 @@ module Axlsx
106
106
  end
107
107
  alias :gapDepth= :gap_depth=
108
108
 
109
- # The shabe of the bars or columns
109
+ # The shape of the bars or columns
110
110
  # must be one of [:cone, :coneToMax, :box, :cylinder, :pyramid, :pyramidToMax]
111
111
  def shape=(v)
112
112
  RestrictionValidator.validate "BarChart.shape", [:cone, :coneToMax, :box, :cylinder, :pyramid, :pyramidToMax], v
@@ -15,9 +15,8 @@ module Axlsx
15
15
  # @return [Array, SimpleTypedList]
16
16
  attr_reader :labels
17
17
 
18
- # The shabe of the bars or columns
19
- # must be one of [:percentStacked, :clustered, :standard, :stacked]
20
- # @return [Symbol]
18
+ # The shape of the bars or columns
19
+ # @return [Symbol] must be one of [:cone, :coneToMax, :box, :cylinder, :pyramid, :pyramidToMax]
21
20
  attr_reader :shape
22
21
 
23
22
  # An array of rgb colors to apply to your bar chart.
@@ -41,8 +40,7 @@ module Axlsx
41
40
  # @see colors
42
41
  def colors=(v) DataTypeValidator.validate "BarSeries.colors", [Array], v; @colors = v end
43
42
 
44
- # The shabe of the bars or columns
45
- # must be one of [:cone, :coneToMax, :box, :cylinder, :pyramid, :pyramidToMax]
43
+ # @see shape
46
44
  def shape=(v)
47
45
  RestrictionValidator.validate "BarSeries.shape", [:cone, :coneToMax, :box, :cylinder, :pyramid, :pyramidToMax], v
48
46
  @shape = v
@@ -55,7 +55,7 @@ module Axlsx
55
55
 
56
56
  # @see DLbls#d_lbl_pos
57
57
  # Assigns the label postion for this data labels on this chart.
58
- # Allowed positions are :bestFilt, :b, :ctr, :inBase, :inEnd, :l,
58
+ # Allowed positions are :bestFit, :b, :ctr, :inBase, :inEnd, :l,
59
59
  # :outEnd, :r and :t
60
60
  # The default is :bestFit
61
61
  # @param [Symbol] label_position the postion you want to use.
@@ -7,13 +7,15 @@ module Axlsx
7
7
  # @param [String] str
8
8
  # @return [String]
9
9
  def to_xml_string(str = '')
10
+ clean_value = Axlsx::trust_input ? @text.to_s : ::CGI.escapeHTML(Axlsx::sanitize(@text.to_s))
11
+
10
12
  str << '<c:tx>'
11
13
  str << '<c:strRef>'
12
14
  str << ('<c:f>' << Axlsx::cell_range([@cell]) << '</c:f>')
13
15
  str << '<c:strCache>'
14
16
  str << '<c:ptCount val="1"/>'
15
17
  str << '<c:pt idx="0">'
16
- str << ('<c:v>' << @text << '</c:v>')
18
+ str << ('<c:v>' << clean_value << '</c:v>')
17
19
  str << '</c:pt>'
18
20
  str << '</c:strCache>'
19
21
  str << '</c:strRef>'
@@ -62,6 +62,7 @@ module Axlsx
62
62
  def to_xml_string(str = '')
63
63
  str << '<c:title>'
64
64
  unless @text.empty?
65
+ clean_value = Axlsx::trust_input ? @text.to_s : ::CGI.escapeHTML(Axlsx::sanitize(@text.to_s))
65
66
  str << '<c:tx>'
66
67
  if @cell.is_a?(Cell)
67
68
  str << '<c:strRef>'
@@ -69,7 +70,7 @@ module Axlsx
69
70
  str << '<c:strCache>'
70
71
  str << '<c:ptCount val="1"/>'
71
72
  str << '<c:pt idx="0">'
72
- str << ('<c:v>' << @text << '</c:v>')
73
+ str << ('<c:v>' << clean_value << '</c:v>')
73
74
  str << '</c:pt>'
74
75
  str << '</c:strCache>'
75
76
  str << '</c:strRef>'
@@ -80,7 +81,7 @@ module Axlsx
80
81
  str << '<a:p>'
81
82
  str << '<a:r>'
82
83
  str << ('<a:rPr sz="' << @text_size.to_s << '"/>')
83
- str << ('<a:t>' << @text.to_s << '</a:t>')
84
+ str << ('<a:t>' << clean_value << '</a:t>')
84
85
  str << '</a:r>'
85
86
  str << '</a:p>'
86
87
  str << '</c:rich>'
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
  module Axlsx
3
3
  # Package is responsible for managing all the bits and peices that Open Office XML requires to make a valid
4
- # xlsx document including valdation and serialization.
4
+ # xlsx document including validation and serialization.
5
5
  class Package
6
6
  include Axlsx::OptionsParser
7
7
 
@@ -68,13 +68,6 @@ module Axlsx
68
68
  @workbook
69
69
  end
70
70
 
71
- #def self.parse(input, confirm_valid = false)
72
- # p = Package.new
73
- # z = Zip::File.open(input)
74
- # p.workbook = Workbook.parse z.get_entry(WORKBOOK_PN)
75
- # p
76
- #end
77
-
78
71
  # @see workbook
79
72
  def workbook=(workbook) DataTypeValidator.validate :Package_workbook, Workbook, workbook; @workbook = workbook; end
80
73
 
@@ -139,7 +132,7 @@ module Axlsx
139
132
  # dcterms and xml namespaces. Those remote schema are included in this gem, and the original files have been altered to
140
133
  # refer to the local versions.
141
134
  #
142
- # If by chance you are able to creat a package that does not validate it indicates that the internal
135
+ # If by chance you are able to create a package that does not validate it indicates that the internal
143
136
  # validation is not robust enough and needs to be improved. Please report your errors to the gem author.
144
137
  # @see http://www.ecma-international.org/publications/standards/Ecma-376.htm
145
138
  # @example
@@ -171,7 +164,7 @@ module Axlsx
171
164
  end
172
165
  unless part[:path].nil?
173
166
  zip.put_next_entry(zip_entry_for_part(part))
174
- zip.write IO.read(part[:path])
167
+ zip.write IO.read(part[:path], mode: "rb")
175
168
  end
176
169
  end
177
170
  zip
@@ -355,4 +348,3 @@ module Axlsx
355
348
  end
356
349
  end
357
350
  end
358
-
@@ -76,7 +76,10 @@ module Axlsx
76
76
  attr_reader :i
77
77
 
78
78
  # Indicates if the font should be rendered underlined
79
- # @return [Boolean]
79
+ # It must be one of :none, :single, :double, :singleAccounting, :doubleAccounting, true, false
80
+ # @return [String]
81
+ # @note
82
+ # true or false is for backwards compatibility and is reassigned to :single or :none respectively
80
83
  attr_reader :u
81
84
 
82
85
  # Indicates if the font should be rendered with a strikthrough
@@ -118,7 +121,12 @@ module Axlsx
118
121
  # @see i
119
122
  def i=(v) Axlsx::validate_boolean v; @i = v end
120
123
  # @see u
121
- def u=(v) Axlsx::validate_boolean v; @u = v end
124
+ def u=(v)
125
+ v = :single if (v == true || v == 1 || v == :true || v == 'true')
126
+ v = :none if (v == false || v == 0 || v == :false || v == 'false')
127
+ Axlsx::validate_cell_u v
128
+ @u = v
129
+ end
122
130
  # @see strike
123
131
  def strike=(v) Axlsx::validate_boolean v; @strike = v end
124
132
  # @see outline
@@ -92,7 +92,7 @@ module Axlsx
92
92
 
93
93
  # Requires that the value is a Integer or Float and is greater or equal to 0
94
94
  # @param [Any] v The value validated
95
- # @raise [ArgumentError] raised if the value is not a Fixnun, Integer, Float value greater or equal to 0
95
+ # @raise [ArgumentError] raised if the value is not a Integer, Float value greater or equal to 0
96
96
  # @return [Boolean] true if the data is valid
97
97
  def self.validate_unsigned_numeric(v)
98
98
  DataTypeValidator.validate(:unsigned_numeric, Numeric, v, UINT_VALIDATOR)
@@ -1,5 +1,5 @@
1
1
  module Axlsx
2
2
 
3
3
  # The current version
4
- VERSION = "3.0.1"
4
+ VERSION = "3.0.2"
5
5
  end
@@ -197,15 +197,6 @@ require 'axlsx/workbook/worksheet/selection.rb'
197
197
  @worksheets[index] if index
198
198
  end
199
199
 
200
- # lets come back to this later when we are ready for parsing.
201
- #def self.parse entry
202
- # io = entry.get_input_stream
203
- # w = self.new
204
- # w.parser_xml = Nokogiri::XML(io.read)
205
- # w.parse_string :date1904, "//xmlns:workbookPr/@date1904"
206
- # w
207
- #end
208
-
209
200
  # Creates a new Workbook
210
201
  # The recomended way to work with workbooks is via Package#workbook
211
202
  # @option options [Boolean] date1904. If this is not specified, date1904 is set to false. Office 2011 for Mac defaults to false.
@@ -12,7 +12,7 @@ module Axlsx
12
12
 
13
13
  # @param [Row] row The row this cell belongs to.
14
14
  # @param [Any] value The value associated with this cell.
15
- # @option options [Symbol] type The intended data type for this cell. If not specified the data type will be determined internally based on the vlue provided.
15
+ # @option options [Symbol] type The intended data type for this cell. If not specified the data type will be determined internally based on the value provided.
16
16
  # @option options [Integer] style The index of the cellXfs item to be applied to this cell. If not specified, the default style (0) will be applied.
17
17
  # @option options [String] font_name
18
18
  # @option options [Integer] charset
@@ -30,6 +30,10 @@ module Axlsx
30
30
  # @option options [String] color an 8 letter rgb specification
31
31
  # @option options [Number] formula_value The value to cache for a formula cell.
32
32
  # @option options [Symbol] scheme must be one of :none, major, :minor
33
+ # @option options [Boolean] escape_formulas - Whether to treat a value starting with an equal
34
+ # sign as formula (default) or as simple string.
35
+ # Allowing user generated data to be interpreted as formulas can be dangerous
36
+ # (see https://www.owasp.org/index.php/CSV_Injection for details).
33
37
  def initialize(row, value = nil, options = {})
34
38
  @row = row
35
39
  # Do not use instance vars if not needed to use less RAM
@@ -38,6 +42,8 @@ module Axlsx
38
42
  type = options.delete(:type) || cell_type_from_value(value)
39
43
  self.type = type unless type == :string
40
44
 
45
+ escape_formulas = options[:escape_formulas]
46
+ self.escape_formulas = escape_formulas unless escape_formulas.nil?
41
47
 
42
48
  val = options.delete(:style)
43
49
  self.style = val unless val.nil? || val == 0
@@ -102,6 +108,18 @@ module Axlsx
102
108
  self.value = @value unless !defined?(@value) || @value.nil?
103
109
  end
104
110
 
111
+ # Whether to treat a value starting with an equal
112
+ # sign as formula (default) or as simple string.
113
+ # Allowing user generated data to be interpreted as formulas can be dangerous
114
+ # (see https://www.owasp.org/index.php/CSV_Injection for details).
115
+ # @return [Boolean]
116
+ attr_reader :escape_formulas
117
+
118
+ def escape_formulas=(v)
119
+ Axlsx.validate_boolean(v)
120
+ @escape_formulas = v
121
+ end
122
+
105
123
  # The value of this cell.
106
124
  # @return [String, Integer, Float, Time, Boolean] casted value based on cell's type attribute.
107
125
  attr_reader :value
@@ -324,6 +342,8 @@ module Axlsx
324
342
  end
325
343
 
326
344
  def is_formula?
345
+ return false if escape_formulas
346
+
327
347
  type == :string && @value.to_s.start_with?(?=)
328
348
  end
329
349
 
@@ -353,6 +373,7 @@ module Axlsx
353
373
  # @return [Float]
354
374
  def autowidth
355
375
  return if is_formula? || value.nil?
376
+
356
377
  if contains_rich_text?
357
378
  string_width('', font_size) + value.autowidth
358
379
  elsif styles.cellXfs[style].alignment && styles.cellXfs[style].alignment.wrap_text
@@ -389,7 +410,7 @@ module Axlsx
389
410
  # - scaling is not linear as font sizes increase
390
411
  def string_width(string, font_size)
391
412
  font_scale = font_size / 10.0
392
- (string.to_s.count(Worksheet::THIN_CHARS) + 3.0) * font_scale
413
+ (string.to_s.size + 3) * font_scale
393
414
  end
394
415
 
395
416
  # we scale the font size if bold style is applied to either the style font or
@@ -4,6 +4,10 @@ module Axlsx
4
4
  # The Col class defines column attributes for columns in sheets.
5
5
  class Col
6
6
 
7
+ # Maximum column width limit in MS Excel is 255 characters
8
+ # https://support.microsoft.com/en-us/office/excel-specifications-and-limits-1672b34d-7043-467e-8e27-269d656771c3
9
+ MAX_WIDTH = 255
10
+
7
11
  include Axlsx::OptionsParser
8
12
  include Axlsx::SerializedAttributes
9
13
  # Create a new Col objects
@@ -111,10 +115,10 @@ module Axlsx
111
115
  # TODO!!!
112
116
  #Axlsx.validate_unsigned_numeric(v) unless v == nil
113
117
  @custom_width = @best_fit = v != nil
114
- @width = v
118
+ @width = v.nil? ? v : [v, MAX_WIDTH].min
115
119
  end
116
120
 
117
- # updates the width for this col based on the cells autowidth and
121
+ # updates the width for this col based on the cells autowidth and
118
122
  # an optionally specified fixed width
119
123
  # @param [Cell] cell The cell to use in updating this col's width
120
124
  # @param [Integer] fixed_width If this is specified the width is set
@@ -127,8 +131,8 @@ module Axlsx
127
131
  elsif use_autowidth
128
132
  cell_width = cell.autowidth
129
133
  self.width = cell_width unless (width || 0) > (cell_width || 0)
130
- end
131
- end
134
+ end
135
+ end
132
136
 
133
137
  # Serialize this columns data to an xml string
134
138
  # @param [String] str