caxlsx 3.0.1 → 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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