write_xlsx 1.12.3 → 1.15.0

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 (118) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +22 -0
  3. data/Changes +23 -0
  4. data/README.md +1 -1
  5. data/lib/write_xlsx/chart/area.rb +2 -2
  6. data/lib/write_xlsx/chart/axis.rb +55 -32
  7. data/lib/write_xlsx/chart/axis_writer.rb +528 -0
  8. data/lib/write_xlsx/chart/bar.rb +2 -2
  9. data/lib/write_xlsx/chart/caption.rb +16 -9
  10. data/lib/write_xlsx/chart/chart_area.rb +121 -0
  11. data/lib/write_xlsx/chart/column.rb +2 -2
  12. data/lib/write_xlsx/chart/d_pt_point_writer.rb +14 -0
  13. data/lib/write_xlsx/chart/doughnut.rb +0 -3
  14. data/lib/write_xlsx/chart/formatting_writer.rb +652 -0
  15. data/lib/write_xlsx/chart/initialization.rb +100 -0
  16. data/lib/write_xlsx/chart/line.rb +4 -3
  17. data/lib/write_xlsx/chart/pie.rb +6 -2
  18. data/lib/write_xlsx/chart/radar.rb +2 -2
  19. data/lib/write_xlsx/chart/scatter.rb +4 -3
  20. data/lib/write_xlsx/chart/series.rb +35 -15
  21. data/lib/write_xlsx/chart/series_data.rb +132 -0
  22. data/lib/write_xlsx/chart/series_writer.rb +318 -0
  23. data/lib/write_xlsx/chart/settings.rb +226 -0
  24. data/lib/write_xlsx/chart/stock.rb +2 -2
  25. data/lib/write_xlsx/chart/table.rb +50 -0
  26. data/lib/write_xlsx/chart/xml_writer.rb +305 -0
  27. data/lib/write_xlsx/chart.rb +286 -2477
  28. data/lib/write_xlsx/chartsheet.rb +35 -83
  29. data/lib/write_xlsx/constants.rb +11 -0
  30. data/lib/write_xlsx/drawing.rb +5 -3
  31. data/lib/write_xlsx/format/alignment_state.rb +39 -0
  32. data/lib/write_xlsx/format/alignment_style.rb +92 -0
  33. data/lib/write_xlsx/format/border_state.rb +47 -0
  34. data/lib/write_xlsx/format/border_style.rb +116 -0
  35. data/lib/write_xlsx/format/fill_state.rb +26 -0
  36. data/lib/write_xlsx/format/fill_style.rb +52 -0
  37. data/lib/write_xlsx/format/font_state.rb +74 -0
  38. data/lib/write_xlsx/format/font_style.rb +172 -0
  39. data/lib/write_xlsx/format/format_state.rb +65 -0
  40. data/lib/write_xlsx/format/number_format_state.rb +20 -0
  41. data/lib/write_xlsx/format/number_format_style.rb +28 -0
  42. data/lib/write_xlsx/format/protection_state.rb +20 -0
  43. data/lib/write_xlsx/format/protection_style.rb +28 -0
  44. data/lib/write_xlsx/format.rb +1093 -426
  45. data/lib/write_xlsx/formats.rb +0 -2
  46. data/lib/write_xlsx/image_property.rb +4 -1
  47. data/lib/write_xlsx/inserted_chart.rb +1 -1
  48. data/lib/write_xlsx/object_positioning.rb +203 -0
  49. data/lib/write_xlsx/package/app.rb +3 -3
  50. data/lib/write_xlsx/package/button.rb +6 -2
  51. data/lib/write_xlsx/package/comments.rb +11 -3
  52. data/lib/write_xlsx/package/conditional_format.rb +7 -3
  53. data/lib/write_xlsx/package/content_types.rb +2 -2
  54. data/lib/write_xlsx/package/core.rb +2 -2
  55. data/lib/write_xlsx/package/custom.rb +3 -2
  56. data/lib/write_xlsx/package/metadata.rb +2 -2
  57. data/lib/write_xlsx/package/packager.rb +0 -3
  58. data/lib/write_xlsx/package/relationships.rb +2 -2
  59. data/lib/write_xlsx/package/rich_value.rb +4 -2
  60. data/lib/write_xlsx/package/rich_value_rel.rb +2 -2
  61. data/lib/write_xlsx/package/rich_value_structure.rb +2 -2
  62. data/lib/write_xlsx/package/rich_value_types.rb +3 -3
  63. data/lib/write_xlsx/package/shared_strings.rb +2 -2
  64. data/lib/write_xlsx/package/styles.rb +13 -9
  65. data/lib/write_xlsx/package/table.rb +8 -2
  66. data/lib/write_xlsx/package/theme.rb +0 -3
  67. data/lib/write_xlsx/package/vml.rb +2 -2
  68. data/lib/write_xlsx/page_setup.rb +192 -0
  69. data/lib/write_xlsx/shape.rb +97 -100
  70. data/lib/write_xlsx/sheets.rb +9 -4
  71. data/lib/write_xlsx/sparkline.rb +2 -2
  72. data/lib/write_xlsx/utility/cell_reference.rb +124 -0
  73. data/lib/write_xlsx/utility/chart_formatting.rb +262 -0
  74. data/lib/write_xlsx/utility/common.rb +44 -0
  75. data/lib/write_xlsx/utility/date_time.rb +113 -0
  76. data/lib/write_xlsx/utility/dimensions.rb +40 -0
  77. data/lib/write_xlsx/utility/drawing.rb +136 -0
  78. data/lib/write_xlsx/utility/rich_text.rb +184 -0
  79. data/lib/write_xlsx/utility/sheetname_quoting.rb +73 -0
  80. data/lib/write_xlsx/utility/string_width.rb +45 -0
  81. data/lib/write_xlsx/utility/url.rb +27 -0
  82. data/lib/write_xlsx/utility/xml_primitives.rb +32 -0
  83. data/lib/write_xlsx/version.rb +1 -1
  84. data/lib/write_xlsx/workbook/chart_data.rb +188 -0
  85. data/lib/write_xlsx/workbook/format_preparation.rb +199 -0
  86. data/lib/write_xlsx/workbook/initialization.rb +223 -0
  87. data/lib/write_xlsx/workbook/package_preparation.rb +231 -0
  88. data/lib/write_xlsx/workbook/workbook_writer.rb +164 -0
  89. data/lib/write_xlsx/workbook.rb +143 -981
  90. data/lib/write_xlsx/worksheet/asset_manager.rb +60 -0
  91. data/lib/write_xlsx/worksheet/autofilter.rb +390 -0
  92. data/lib/write_xlsx/worksheet/cell_data.rb +13 -6
  93. data/lib/write_xlsx/worksheet/cell_data_manager.rb +47 -0
  94. data/lib/write_xlsx/worksheet/cell_data_store.rb +61 -0
  95. data/lib/write_xlsx/worksheet/columns.rb +204 -0
  96. data/lib/write_xlsx/worksheet/comments_support.rb +61 -0
  97. data/lib/write_xlsx/worksheet/conditional_formats.rb +30 -0
  98. data/lib/write_xlsx/worksheet/data_validation.rb +9 -1
  99. data/lib/write_xlsx/worksheet/data_writing.rb +1017 -0
  100. data/lib/write_xlsx/worksheet/drawing_methods.rb +308 -0
  101. data/lib/write_xlsx/worksheet/drawing_preparation.rb +290 -0
  102. data/lib/write_xlsx/worksheet/drawing_relations.rb +76 -0
  103. data/lib/write_xlsx/worksheet/drawing_xml_writer.rb +50 -0
  104. data/lib/write_xlsx/worksheet/formatting.rb +418 -0
  105. data/lib/write_xlsx/worksheet/hyperlink.rb +9 -1
  106. data/lib/write_xlsx/worksheet/initialization.rb +146 -0
  107. data/lib/write_xlsx/worksheet/panes.rb +64 -0
  108. data/lib/write_xlsx/worksheet/print_options.rb +72 -0
  109. data/lib/write_xlsx/worksheet/protection.rb +65 -0
  110. data/lib/write_xlsx/worksheet/rich_text_helpers.rb +78 -0
  111. data/lib/write_xlsx/worksheet/row_col_sizing.rb +69 -0
  112. data/lib/write_xlsx/worksheet/rows.rb +84 -0
  113. data/lib/write_xlsx/worksheet/selection.rb +41 -0
  114. data/lib/write_xlsx/worksheet/xml_writer.rb +1246 -0
  115. data/lib/write_xlsx/worksheet.rb +376 -4530
  116. metadata +66 -4
  117. data/lib/write_xlsx/utility.rb +0 -986
  118. data/lib/write_xlsx/worksheet/page_setup.rb +0 -192
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Writexlsx
4
+ class Worksheet
5
+ # Print and display options extracted from Worksheet to slim the main class.
6
+ module PrintOptions
7
+ #
8
+ # Set the page orientation as portrait.
9
+ # The default worksheet orientation is portrait, so you won't generally
10
+ # need to call this method.
11
+ #
12
+ def set_portrait
13
+ @page_setup.orientation = true
14
+ @page_setup.page_setup_changed = true
15
+ end
16
+
17
+ #
18
+ # Set the page orientation as landscape.
19
+ #
20
+ def set_landscape
21
+ @page_setup.orientation = false
22
+ @page_setup.page_setup_changed = true
23
+ end
24
+
25
+ #
26
+ # This method is used to display the worksheet in "Page View/Layout" mode.
27
+ #
28
+ def set_page_view(flag = 1)
29
+ @page_view = flag
30
+ end
31
+
32
+ #
33
+ # set_pagebreak_view
34
+ #
35
+ # Set the page view mode.
36
+ #
37
+ def set_pagebreak_view
38
+ @page_view = 2
39
+ end
40
+
41
+ #
42
+ # Set the colour of the worksheet tab.
43
+ #
44
+ def tab_color=(color)
45
+ @tab_color = Colors.new.color(color)
46
+ end
47
+
48
+ # This method is deprecated. use tab_color=().
49
+ def set_tab_color(color)
50
+ put_deprecate_message("#{self}.set_tab_color")
51
+ self.tab_color = color
52
+ end
53
+
54
+ #
55
+ # Store the horizontal page breaks on a worksheet.
56
+ #
57
+ def set_h_pagebreaks(*args)
58
+ breaks = args.collect do |brk|
59
+ Array(brk)
60
+ end.flatten
61
+ @page_setup.hbreaks += breaks
62
+ end
63
+
64
+ #
65
+ # Store the vertical page breaks on a worksheet.
66
+ #
67
+ def set_v_pagebreaks(*args)
68
+ @page_setup.vbreaks += args
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Writexlsx
4
+ class Worksheet
5
+ # Protection-related operations extracted from Worksheet to slim the main class.
6
+ module Protection
7
+ #
8
+ # Set the worksheet protection flags to prevent modification of worksheet
9
+ # objects.
10
+ #
11
+ def protect(password = nil, options = {})
12
+ check_parameter(options, protect_default_settings.keys, 'protect')
13
+ @protect = protect_default_settings.merge(options)
14
+
15
+ # Set the password after the user defined values.
16
+ if password && password != ''
17
+ @protect[:password] =
18
+ encode_password(password)
19
+ end
20
+ end
21
+
22
+ #
23
+ # Unprotect ranges within a protected worksheet.
24
+ #
25
+ def unprotect_range(range, range_name = nil, password = nil)
26
+ if range.nil?
27
+ raise "The range must be defined in unprotect_range())\n"
28
+ else
29
+ range = range.gsub("$", "")
30
+ range = range.sub(/^=/, "")
31
+ @num_protected_ranges += 1
32
+ end
33
+
34
+ range_name ||= "Range#{@num_protected_ranges}"
35
+ password &&= encode_password(password)
36
+
37
+ @protected_ranges << [range, range_name, password]
38
+ end
39
+
40
+ protected
41
+
42
+ def protect_default_settings # :nodoc:
43
+ {
44
+ sheet: true,
45
+ content: false,
46
+ objects: false,
47
+ scenarios: false,
48
+ format_cells: false,
49
+ format_columns: false,
50
+ format_rows: false,
51
+ insert_columns: false,
52
+ insert_rows: false,
53
+ insert_hyperlinks: false,
54
+ delete_columns: false,
55
+ delete_rows: false,
56
+ select_locked_cells: true,
57
+ sort: false,
58
+ autofilter: false,
59
+ pivot_tables: false,
60
+ select_unlocked_cells: true
61
+ }
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Writexlsx
4
+ class Worksheet
5
+ module RichTextHelpers
6
+ def cell_format_of_rich_string(rich_strings)
7
+ # If the last arg is a format we use it as the cell format.
8
+ rich_strings.pop if rich_strings[-1].respond_to?(:xf_index)
9
+ end
10
+
11
+ #
12
+ # Convert the list of format, string tokens to pairs of (format, string)
13
+ # except for the first string fragment which doesn't require a default
14
+ # formatting run. Use the default for strings without a leading format.
15
+ #
16
+ def rich_strings_fragments(rich_strings) # :nodoc:
17
+ # Create a temp format with the default font for unformatted fragments.
18
+ default = Format.new(0)
19
+
20
+ last = 'format'
21
+ pos = 0
22
+ raw_string = ''
23
+
24
+ fragments = []
25
+ rich_strings.each do |token|
26
+ if token.respond_to?(:xf_index)
27
+ # Can't allow 2 formats in a row
28
+ return nil if last == 'format' && pos > 0
29
+
30
+ # Token is a format object. Add it to the fragment list.
31
+ fragments << token
32
+ last = 'format'
33
+ else
34
+ # Token is a string.
35
+ if last == 'format'
36
+ # If previous token was a format just add the string.
37
+ fragments << token
38
+ else
39
+ # If previous token wasn't a format add one before the string.
40
+ fragments << default << token
41
+ end
42
+
43
+ raw_string += token # Keep track of actual string length.
44
+ last = 'string'
45
+ end
46
+ pos += 1
47
+ end
48
+ [fragments, raw_string]
49
+ end
50
+
51
+ def xml_str_of_rich_string(fragments)
52
+ # Create a temp XML::Writer object and use it to write the rich string
53
+ # XML to a string.
54
+ writer = Package::XMLWriterSimple.new
55
+
56
+ # If the first token is a string start the <r> element.
57
+ writer.start_tag('r') unless fragments[0].respond_to?(:xf_index)
58
+
59
+ # Write the XML elements for the format string fragments.
60
+ fragments.each do |token|
61
+ if token.respond_to?(:xf_index)
62
+ # Write the font run.
63
+ writer.start_tag('r')
64
+ token.write_font_rpr(writer, self)
65
+ else
66
+ # Write the string fragment part, with whitespace handling.
67
+ attributes = []
68
+
69
+ attributes << ['xml:space', 'preserve'] if token =~ /^\s/ || token =~ /\s$/
70
+ writer.data_element('t', token, attributes)
71
+ writer.end_tag('r')
72
+ end
73
+ end
74
+ writer.string
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,69 @@
1
+ # -*- coding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+
4
+ require 'write_xlsx/utility/string_width'
5
+
6
+ module Writexlsx
7
+ class Worksheet
8
+ module RowColSizing
9
+ include Writexlsx::Utility::StringWidth
10
+
11
+ #
12
+ # Convert the width of a cell from user's units to pixels. Excel rounds
13
+ # the column width to the nearest pixel. If the width hasn't been set
14
+ # by the user we use the default value. A hidden column is treated as
15
+ # having a width of zero unless it has the special "object_position" of
16
+ # 4 (size with cells).
17
+ #
18
+ def size_col(col, anchor = 0)
19
+ info = col_info[col]
20
+ calculate_col_pixels(
21
+ info&.width,
22
+ info&.hidden,
23
+ anchor
24
+ )
25
+ end
26
+
27
+ #
28
+ # Convert the height of a cell from user's units to pixels. If the height
29
+ # hasn't been set by the user we use the default value. A hidden row is
30
+ # treated as having a height of zero unless it has the special
31
+ # "object_position" of 4 (size with cells).
32
+ #
33
+ def size_row(row, anchor = 0)
34
+ info = row_sizes[row]
35
+ calculate_row_pixels(
36
+ info&.first,
37
+ info&.last,
38
+ anchor
39
+ )
40
+ end
41
+
42
+ private
43
+
44
+ def calculate_col_pixels(width, hidden, anchor)
45
+ width ||= @default_col_width
46
+
47
+ return DEFAULT_COL_PIXELS unless width
48
+
49
+ if hidden == 1 && anchor != 4
50
+ 0
51
+ elsif width < 1
52
+ ((width * (MAX_DIGIT_WIDTH + PADDING)) + 0.5).to_i
53
+ else
54
+ ((width * MAX_DIGIT_WIDTH) + 0.5).to_i + PADDING
55
+ end
56
+ end
57
+
58
+ def calculate_row_pixels(height, hidden, anchor)
59
+ height ||= default_row_height
60
+
61
+ if hidden == 1 && anchor != 4
62
+ 0
63
+ else
64
+ (4 / 3.0 * height).to_i
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Writexlsx
4
+ class Worksheet
5
+ # Row-related operations extracted from Worksheet to slim the main class.
6
+ module Rows
7
+ #
8
+ # :call-seq:
9
+ # set_row(row [ , height, format, hidden, level, collapsed ])
10
+ #
11
+ # This method can be used to change the default properties of a row.
12
+ # All parameters apart from +row+ are optional.
13
+ #
14
+ def set_row(*args)
15
+ return unless args[0]
16
+
17
+ row = args[0]
18
+ height = args[1] || @default_height
19
+ xf = args[2]
20
+ hidden = args[3] || 0
21
+ level = args[4] || 0
22
+ collapsed = args[5] || 0
23
+
24
+ # Use min col in check_dimensions. Default to 0 if undefined.
25
+ min_col = @dim_colmin || 0
26
+
27
+ # Check that row and col are valid and store max and min values.
28
+ check_dimensions(row, min_col)
29
+ store_row_col_max_min_values(row, min_col)
30
+
31
+ height ||= @default_row_height
32
+
33
+ # If the height is 0 the row is hidden and the height is the default.
34
+ if height == 0
35
+ hidden = 1
36
+ height = @default_row_height
37
+ end
38
+
39
+ # Set the limits for the outline levels (0 <= x <= 7).
40
+ level = 0 if level < 0
41
+ level = 7 if level > 7
42
+
43
+ @outline_row_level = level if level > @outline_row_level
44
+
45
+ # Store the row properties.
46
+ @set_rows[row] = [height, xf, hidden, level, collapsed]
47
+
48
+ # Store the row change to allow optimisations.
49
+ @row_size_changed = true
50
+
51
+ # Store the row sizes for use when calculating image vertices.
52
+ @row_sizes[row] = [height, hidden]
53
+ end
54
+
55
+ #
56
+ # This method is used to set the height (in pixels) and the properties of the
57
+ # row.
58
+ #
59
+ def set_row_pixels(*data)
60
+ height = data[1]
61
+
62
+ data[1] = pixels_to_height(height) if ptrue?(height)
63
+ set_row(*data)
64
+ end
65
+
66
+ #
67
+ # Set the default row properties
68
+ #
69
+ def set_default_row(height = nil, zero_height = nil)
70
+ height ||= @original_row_height
71
+ zero_height ||= 0
72
+
73
+ if height != @original_row_height
74
+ @default_row_height = height
75
+
76
+ # Store the row change to allow optimisations.
77
+ @row_size_changed = 1
78
+ end
79
+
80
+ @default_row_zeroed = 1 if ptrue?(zero_height)
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Writexlsx
4
+ class Worksheet
5
+ # Selection-related operations extracted from Worksheet to slim the main class.
6
+ module Selection
7
+ #
8
+ # :call-seq:
9
+ # set_selection(cell_or_cell_range)
10
+ #
11
+ # Set which cell or cells are selected in a worksheet.
12
+ #
13
+ def set_selection(*args)
14
+ return if args.empty?
15
+
16
+ if (row_col_array = row_col_notation(args.first))
17
+ row_first, col_first, row_last, col_last = row_col_array
18
+ else
19
+ row_first, col_first, row_last, col_last = args
20
+ end
21
+
22
+ active_cell = xl_rowcol_to_cell(row_first, col_first)
23
+
24
+ if row_last # Range selection.
25
+ # Swap last row/col for first row/col as necessary
26
+ row_first, row_last = row_last, row_first if row_first > row_last
27
+ col_first, col_last = col_last, col_first if col_first > col_last
28
+
29
+ sqref = xl_range(row_first, row_last, col_first, col_last)
30
+ else # Single cell selection.
31
+ sqref = active_cell
32
+ end
33
+
34
+ # Selection isn't set for cell A1.
35
+ return if sqref == 'A1'
36
+
37
+ @selections = [[nil, active_cell, sqref]]
38
+ end
39
+ end
40
+ end
41
+ end