Class: Xlsxrb::StreamWriter
- Inherits:
-
Object
- Object
- Xlsxrb::StreamWriter
- Defined in:
- lib/xlsxrb.rb
Overview
DSL context for Xlsxrb.generate streaming writes.
Defined Under Namespace
Classes: WorksheetProxy
Instance Attribute Summary collapse
-
#current_sheet ⇒ Object
readonly
Returns the value of attribute current_sheet.
Instance Method Summary collapse
-
#app_property(name, value) ⇒ void
Set an app document property.
-
#auto_filter(range) ⇒ Object
: (String range) -> void.
-
#chart(**options) ⇒ Object
Add a chart to the current sheet.
-
#cleanup! ⇒ Object
Explicitly remove any remaining tempfiles.
-
#close ⇒ Object
: () -> Elements::Workbook.
-
#column(index, width: nil, hidden: false, custom_width: false, outline_level: nil) ⇒ void
Set column width for a 0-based column index.
-
#comment(cell, text, author: "Author") ⇒ Object
: (String | Integer cell, String text, ?author: ::String) -> void.
-
#conditional_format(sqref, **opts) ⇒ Object
: (String sqref, **String | Integer | bool | nil opts) -> void.
-
#core_property(name, value) ⇒ void
Set a core document property.
-
#custom_property(name, value, type: :string) ⇒ void
Add a custom document property.
-
#defined_name(name, value, sheet: nil, hidden: false) ⇒ void
Add a defined name.
-
#filter_column(col_id, filter) ⇒ Object
: (String | Integer col_id, String | Hash[Symbol, String | Integer | bool | nil] filter) -> void.
-
#freeze_pane(row: 0, col: 0) ⇒ void
Freeze panes at the given row and column.
-
#header_footer(**opts) ⇒ Object
: (**String | Integer | bool | nil opts) -> void.
-
#hyperlink(cell, url = nil, display: nil, tooltip: nil, location: nil) ⇒ Object
: (String | Integer cell, ?String? url, ?display: String?, ?tooltip: String?, ?location: String?) -> void.
-
#image(file_data, ext: "png", from_col: 0, from_row: 0, to_col: 5, to_row: 10, **opts) ⇒ Object
: (String file_data, ?ext: ::String, ?from_col: ::Integer, ?from_row: ::Integer, ?to_col: ::Integer, ?to_row: ::Integer, **String | Integer | bool | nil opts) -> void.
-
#initialize(target, strict_excel_mode: true) ⇒ StreamWriter
constructor
: (String | IO target, ?strict_excel_mode: bool) -> void.
-
#internal_sheet_setup(name = nil) {|_self| ... } ⇒ Object
Internal: Start or switch to a named sheet (internal helper).
-
#merge(range = nil, row: nil, col_start: nil, col_end: nil, row_start: nil, row_end: nil) ⇒ void
Merge a range of cells (e.g. "A1:B2"), or by coordinate indices.
-
#page_break_col(col_index) ⇒ Object
: (Integer col_index) -> void.
-
#page_break_row(row_num) ⇒ Object
: (Integer row_num) -> void.
-
#page_margins(left: nil, right: nil, top: nil, bottom: nil, header: nil, footer: nil) ⇒ Object
: (?left: Float?, ?right: Float?, ?top: Float?, ?bottom: Float?, ?header: Float?, ?footer: Float?) -> void.
-
#page_setup(**opts) ⇒ Object
: (**String | Integer | bool | nil opts) -> void.
- #pivot_table(source_ref, row_fields:, data_fields:, col_fields: [], dest_ref: "E1", name: nil, field_names: nil, items: nil) ⇒ Object
-
#print_area(range, sheet: nil) ⇒ Object
Set the print area for the current or named sheet.
-
#print_options(name, value) ⇒ Object
: (Symbol name, String | Integer | bool value) -> void.
-
#print_titles(rows: nil, cols: nil, sheet: nil) ⇒ Object
Set print titles for the current or named sheet.
-
#properties(core: nil, app: nil) ⇒ void
Set multiple core and/or app properties.
-
#protect_sheet(**opts) ⇒ Object
: (**String | Integer | bool | nil opts) -> void.
-
#protect_workbook(**opts) ⇒ void
Set workbook protection.
-
#row(values, styles: nil, height: nil, hidden: false, custom_height: false, outline_level: nil) ⇒ void
Add a row of values.
-
#select_cell(active_cell, sqref: nil, pane: nil) ⇒ Object
: (String active_cell, ?sqref: String?, ?pane: String?) -> void.
-
#shape(preset: "rect", text: nil, from_col: 0, from_row: 0, to_col: 5, to_row: 5, **opts) ⇒ Object
: (?preset: ::String, ?text: String?, ?from_col: ::Integer, ?from_row: ::Integer, ?to_col: ::Integer, ?to_row: ::Integer, **String | Integer | bool | nil opts) -> void.
-
#sheet(name = nil, **opts) {|sheet_builder| ... } ⇒ void
Add a new sheet.
-
#sheet_properties(name, value) ⇒ Object
: (Symbol name, String | Integer | bool | Float value) -> void.
-
#sheet_view(name, value) ⇒ Object
: (Symbol name, String | Integer | bool | Float value) -> void.
-
#sort_state(ref, sort_conditions, **opts) ⇒ Object
: (String ref, Array[String | Hash[Symbol, String | Integer | bool | nil]] sort_conditions, **String | Integer | bool | nil opts) -> void.
-
#sparkline_group(sparklines:, type: nil, **opts) ⇒ Object
: (sparklines: Array, ?type: String?, **String | Integer | bool | nil opts) -> void.
-
#split_pane(x_split: 0, y_split: 0, top_left_cell: nil) ⇒ Object
: (?x_split: ::Integer, ?y_split: ::Integer, ?top_left_cell: String?) -> void.
-
#style(name, **opts) {|style_builder| ... } ⇒ StyleBuilder
Define a named style that can be applied to cells.
-
#table(ref, columns:, name: nil, display_name: nil, style: nil, **opts) ⇒ Object
: (String ref, columns: Array[String | Hash[Symbol, String | Integer | bool | nil]], ?name: String?, ?display_name: String?, ?style: String?, **String | Integer | bool | nil opts) -> void.
-
#validate_data(sqref, **opts) ⇒ Object
: (String sqref, **String | Integer | bool | nil opts) -> void.
-
#workbook_property(name, value) ⇒ void
Set a workbook property.
Constructor Details
#initialize(target, strict_excel_mode: true) ⇒ StreamWriter
: (String | IO target, ?strict_excel_mode: bool) -> void
1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 |
# File 'lib/xlsxrb.rb', line 1452 def initialize(target, strict_excel_mode: true) @target = target @strict_excel_mode = strict_excel_mode @sst = [] @sst_index = {} @sheets = [] @current_sheet = nil @current_row_index = 0 @tempfiles = [] @current_tempfile = nil @current_row_writer = nil @current_columns = [] @current_charts = [] @current_hyperlinks = [] @current_auto_filter = nil @current_filter_columns = {} @current_sort_state = nil @current_data_validations = [] @current_conditional_formats = [] @current_tables = [] @current_comments = [] @current_merge_cells = [] @current_freeze_pane = nil @current_split_pane = nil @current_selection = nil @current_page_margins = nil @current_page_setup = {} @current_header_footer = {} @current_print_options = {} @current_sheet_protection = nil @current_images = [] @current_shapes = [] @current_sheet_properties = {} @current_sheet_view = {} @current_row_breaks = [] @current_col_breaks = [] @styles = {} # { style_name => StyleBuilder } @style_writer = Ooxml::Writer.new @style_name_to_id = {} # Workbook-level settings @defined_names = [] @core_properties = {} @app_properties = {} @custom_properties = [] @workbook_protection = nil @workbook_properties = { update_links: "never" } end |
Instance Attribute Details
#current_sheet ⇒ Object (readonly)
Returns the value of attribute current_sheet.
1449 1450 1451 |
# File 'lib/xlsxrb.rb', line 1449 def current_sheet @current_sheet end |
Instance Method Details
#app_property(name, value) ⇒ void
This method returns an undefined value.
Set an app document property.
: (Symbol name, String | Integer | Time value) -> void
2421 2422 2423 |
# File 'lib/xlsxrb.rb', line 2421 def app_property(name, value) @app_properties[name] = value end |
#auto_filter(range) ⇒ Object
: (String range) -> void
2129 2130 2131 2132 |
# File 'lib/xlsxrb.rb', line 2129 def auto_filter(range) sheet if @current_sheet.nil? @current_auto_filter = range end |
#chart(**options) ⇒ Object
Add a chart to the current sheet. : (**String | Integer | bool | nil options) ?{ (ChartBuilder) -> void } -> void
2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 |
# File 'lib/xlsxrb.rb', line 2101 def chart(**) sheet if @current_sheet.nil? if block_given? builder = ChartBuilder.new yield builder = builder..merge() end @current_charts << end |
#cleanup! ⇒ Object
Explicitly remove any remaining tempfiles. Called via ensure block. : () -> void
2482 2483 2484 2485 2486 2487 2488 |
# File 'lib/xlsxrb.rb', line 2482 def cleanup! @tempfiles.each do |tmp| tmp.close tmp.unlink end @tempfiles.clear end |
#close ⇒ Object
: () -> Elements::Workbook
2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 |
# File 'lib/xlsxrb.rb', line 2448 def close raise ArgumentError, "Workbook must contain at least one sheet (Excel limitation)" if @strict_excel_mode && @sheets.empty? && @current_sheet.nil? Xlsxrb.in_span("StreamWriter#close") do flush_current_sheet styles_definition = { fonts: @style_writer.fonts.dup, fills: @style_writer.fills.dup, borders: @style_writer.borders.dup, xf_entries: @style_writer.xf_entries.dup, num_fmts: @style_writer.num_fmts.dup } resolved_names = resolve_defined_names(@defined_names, @sheets) Ooxml::WorkbookWriter.write( @target, sheets: @sheets, shared_strings: @sst, styles: styles_definition, defined_names: resolved_names.empty? ? nil : resolved_names, core_properties: @core_properties.empty? ? nil : @core_properties, app_properties: @app_properties.empty? ? nil : @app_properties, custom_properties: @custom_properties.empty? ? nil : @custom_properties, workbook_protection: @workbook_protection ) end ensure cleanup! end |
#column(index, width: nil, hidden: false, custom_width: false, outline_level: nil) ⇒ void
Excel's column width max is 255.
This method returns an undefined value.
Set column width for a 0-based column index. Add a column to the sheet.
: (Integer | String | Range[Integer | String] | Array[Integer | String] index, ?width: Float | Integer | nil, ?hidden: bool, ?custom_width: bool, ?outline_level: Integer | nil) -> void
2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 |
# File 'lib/xlsxrb.rb', line 2082 def column(index, width: nil, hidden: false, custom_width: false, outline_level: nil) raise ArgumentError, "Column width #{width} must be between 0 and 255 characters (Excel limitation)" if @strict_excel_mode && width && (width.negative? || width > 255) indices = case index when Range, Array index.map { |i| Elements::Cell.column_index(i) } else [Elements::Cell.column_index(index)] end sheet if @current_sheet.nil? indices.each do |idx| @current_columns << { index: idx, width: width, hidden: hidden, custom_width: custom_width || !width.nil?, outline_level: outline_level } end end |
#comment(cell, text, author: "Author") ⇒ Object
: (String | Integer cell, String text, ?author: ::String) -> void
2192 2193 2194 2195 |
# File 'lib/xlsxrb.rb', line 2192 def comment(cell, text, author: "Author") sheet if @current_sheet.nil? @current_comments << { cell: cell, text: text, author: } end |
#conditional_format(sqref, **opts) ⇒ Object
: (String sqref, **String | Integer | bool | nil opts) -> void
2157 2158 2159 2160 |
# File 'lib/xlsxrb.rb', line 2157 def conditional_format(sqref, **opts) sheet if @current_sheet.nil? @current_conditional_formats << opts.merge(sqref: sqref) end |
#core_property(name, value) ⇒ void
This method returns an undefined value.
Set a core document property.
: (Symbol name, String | Integer | Time value) -> void
2411 2412 2413 |
# File 'lib/xlsxrb.rb', line 2411 def core_property(name, value) @core_properties[name] = value end |
#custom_property(name, value, type: :string) ⇒ void
This method returns an undefined value.
Add a custom document property.
: (String name, String | Integer | Float | bool | Time value, ?type: ::Symbol) -> void
2443 2444 2445 |
# File 'lib/xlsxrb.rb', line 2443 def custom_property(name, value, type: :string) @custom_properties << { name: name, value: value, type: type } end |
#defined_name(name, value, sheet: nil, hidden: false) ⇒ void
This method returns an undefined value.
Add a defined name.
: (String name, String value, ?sheet: String?, ?hidden: bool) -> void
2366 2367 2368 2369 2370 2371 2372 2373 |
# File 'lib/xlsxrb.rb', line 2366 def defined_name(name, value, sheet: nil, hidden: false) entry = { name: name, value: value, hidden: hidden } if sheet # local_sheet_id will be resolved at close time entry[:local_sheet_name] = sheet end @defined_names << entry end |
#filter_column(col_id, filter) ⇒ Object
: (String | Integer col_id, String | Hash[Symbol, String | Integer | bool | nil] filter) -> void
2135 2136 2137 2138 |
# File 'lib/xlsxrb.rb', line 2135 def filter_column(col_id, filter) sheet if @current_sheet.nil? @current_filter_columns[col_id] = filter end |
#freeze_pane(row: 0, col: 0) ⇒ void
This method returns an undefined value.
Freeze panes at the given row and column.
: (?row: ::Integer, ?col: ::Integer) -> void
2243 2244 2245 2246 2247 |
# File 'lib/xlsxrb.rb', line 2243 def freeze_pane(row: 0, col: 0) col = Elements::Cell.column_index(col) sheet if @current_sheet.nil? @current_freeze_pane = { row: row, col: col } end |
#header_footer(**opts) ⇒ Object
: (**String | Integer | bool | nil opts) -> void
2277 2278 2279 2280 |
# File 'lib/xlsxrb.rb', line 2277 def (**opts) sheet if @current_sheet.nil? @current_header_footer.merge!(opts) end |
#hyperlink(cell, url = nil, display: nil, tooltip: nil, location: nil) ⇒ Object
: (String | Integer cell, ?String? url, ?display: String?, ?tooltip: String?, ?location: String?) -> void
2116 2117 2118 2119 2120 2121 2122 2123 2124 |
# File 'lib/xlsxrb.rb', line 2116 def hyperlink(cell, url = nil, display: nil, tooltip: nil, location: nil) sheet if @current_sheet.nil? link = { cell: cell } link[:url] = url if url link[:display] = display if display link[:tooltip] = tooltip if tooltip link[:location] = location if location @current_hyperlinks << link end |
#image(file_data, ext: "png", from_col: 0, from_row: 0, to_col: 5, to_row: 10, **opts) ⇒ Object
: (String file_data, ?ext: ::String, ?from_col: ::Integer, ?from_row: ::Integer, ?to_col: ::Integer, ?to_row: ::Integer, **String | Integer | bool | nil opts) -> void
2309 2310 2311 2312 2313 2314 |
# File 'lib/xlsxrb.rb', line 2309 def image(file_data, ext: "png", from_col: 0, from_row: 0, to_col: 5, to_row: 10, **opts) sheet if @current_sheet.nil? img = { file_data: file_data, ext: ext, from_col: from_col, from_row: from_row, to_col: to_col, to_row: to_row } img.merge!(opts) @current_images << img end |
#internal_sheet_setup(name = nil) {|_self| ... } ⇒ Object
Internal: Start or switch to a named sheet (internal helper). : (?String? name) ?{ (WorksheetProxy) -> void } -> (WorksheetProxy | nil)
1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 |
# File 'lib/xlsxrb.rb', line 1925 def internal_sheet_setup(name = nil) flush_current_sheet name ||= "Sheet#{@sheets.size + 1}" @current_sheet = name @current_row_index = 0 @current_tempfile = Tempfile.new(["xlsxrb_rows", ".xml"]) @current_tempfile.binmode @current_row_writer = Ooxml::WorksheetWriter.new(@current_tempfile) @current_row_writer.instance_variable_set(:@started, true) @current_columns = [] @current_charts = [] @current_hyperlinks = [] @current_auto_filter = nil @current_filter_columns = {} @current_sort_state = nil @current_data_validations = [] @current_conditional_formats = [] @current_tables = [] @current_pivot_tables = [] @current_sparkline_groups = [] @current_comments = [] @current_merge_cells = [] @current_freeze_pane = nil @current_split_pane = nil @current_selection = nil @current_page_margins = nil @current_page_setup = {} @current_header_footer = {} @current_print_options = {} @current_sheet_protection = nil @current_images = [] @current_shapes = [] @current_sheet_properties = {} @current_sheet_view = {} @current_row_breaks = [] @current_col_breaks = [] @current_cells = {} return unless block_given? yield self flush_current_sheet end |
#merge(range = nil, row: nil, col_start: nil, col_end: nil, row_start: nil, row_end: nil) ⇒ void
This method returns an undefined value.
Merge a range of cells (e.g. "A1:B2"), or by coordinate indices.
: (?String? range, ?String? row, ?String? col_start, ?String? col_end, ?String? row_start, ?String? row_end) -> void
2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 |
# File 'lib/xlsxrb.rb', line 2218 def merge(range = nil, row: nil, col_start: nil, col_end: nil, row_start: nil, row_end: nil) sheet if @current_sheet.nil? if range raise ArgumentError, "Invalid merge range format: '#{range}'. Expected format like 'A1:B2'." if @strict_excel_mode && !range.match?(/^[A-Za-z]{1,3}\d+(:[A-Za-z]{1,3}\d+)?$/) @current_merge_cells << range else r_start = row || row_start || 0 r_end = row || row_end || 0 c_start = col_start || 0 c_end = col_end || 0 start_ref = "#{Xlsxrb::Elements::Cell.column_letter(c_start)}#{r_start + 1}" end_ref = "#{Xlsxrb::Elements::Cell.column_letter(c_end)}#{r_end + 1}" @current_merge_cells << "#{start_ref}:#{end_ref}" end end |
#page_break_col(col_index) ⇒ Object
: (Integer col_index) -> void
2350 2351 2352 2353 2354 |
# File 'lib/xlsxrb.rb', line 2350 def page_break_col(col_index) col_index = Elements::Cell.column_index(col_index) sheet if @current_sheet.nil? @current_col_breaks << col_index end |
#page_break_row(row_num) ⇒ Object
: (Integer row_num) -> void
2344 2345 2346 2347 |
# File 'lib/xlsxrb.rb', line 2344 def page_break_row(row_num) sheet if @current_sheet.nil? @current_row_breaks << row_num end |
#page_margins(left: nil, right: nil, top: nil, bottom: nil, header: nil, footer: nil) ⇒ Object
: (?left: Float?, ?right: Float?, ?top: Float?, ?bottom: Float?, ?header: Float?, ?footer: Float?) -> void
2265 2266 2267 2268 |
# File 'lib/xlsxrb.rb', line 2265 def page_margins(left: nil, right: nil, top: nil, bottom: nil, header: nil, footer: nil) sheet if @current_sheet.nil? @current_page_margins = { left: left, right: right, top: top, bottom: bottom, header: header, footer: }.compact end |
#page_setup(**opts) ⇒ Object
: (**String | Integer | bool | nil opts) -> void
2271 2272 2273 2274 |
# File 'lib/xlsxrb.rb', line 2271 def page_setup(**opts) sheet if @current_sheet.nil? @current_page_setup.merge!(opts) end |
#pivot_table(source_ref, row_fields:, data_fields:, col_fields: [], dest_ref: "E1", name: nil, field_names: nil, items: nil) ⇒ Object
2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 |
# File 'lib/xlsxrb.rb', line 2178 def pivot_table(source_ref, row_fields:, data_fields:, col_fields: [], dest_ref: "E1", name: nil, field_names: nil, items: nil) sheet if @current_sheet.nil? @current_pivot_tables ||= [] @current_pivot_tables << { source_ref: source_ref, row_fields: row_fields, data_fields: data_fields, col_fields: col_fields, dest_ref: dest_ref, name: name, field_names: field_names, items: items } end |
#print_area(range, sheet: nil) ⇒ Object
Set the print area for the current or named sheet. : (String range, ?sheet: String?) -> void
2377 2378 2379 2380 2381 2382 |
# File 'lib/xlsxrb.rb', line 2377 def print_area(range, sheet: nil) sheet_name = sheet || @current_sheet || "Sheet1" value = "'#{sheet_name}'!#{absolute_range(range)}" @defined_names.reject! { |dn| dn[:name] == "_xlnm.Print_Area" && dn[:local_sheet_name] == sheet_name } defined_name("_xlnm.Print_Area", value, sheet: sheet_name) end |
#print_options(name, value) ⇒ Object
: (Symbol name, String | Integer | bool value) -> void
2283 2284 2285 2286 |
# File 'lib/xlsxrb.rb', line 2283 def (name, value) sheet if @current_sheet.nil? @current_print_options[name] = value end |
#print_titles(rows: nil, cols: nil, sheet: nil) ⇒ Object
Set print titles for the current or named sheet. : (?rows: String?, ?cols: String?, ?sheet: String?) -> void
2386 2387 2388 2389 2390 2391 2392 2393 2394 |
# File 'lib/xlsxrb.rb', line 2386 def print_titles(rows: nil, cols: nil, sheet: nil) sheet_name = sheet || @current_sheet || "Sheet1" parts = [] parts << "'#{sheet_name}'!$#{cols.sub(":", ":$")}" if cols parts << "'#{sheet_name}'!$#{rows.sub(":", ":$")}" if rows value = parts.join(",") @defined_names.reject! { |dn| dn[:name] == "_xlnm.Print_Titles" && dn[:local_sheet_name] == sheet_name } defined_name("_xlnm.Print_Titles", value, sheet: sheet_name) end |
#properties(core: nil, app: nil) ⇒ void
This method returns an undefined value.
Set multiple core and/or app properties.
: (?core: Hash[Symbol, String | Integer | Time]?, ?app: Hash[Symbol, String | Integer | Time]?) -> void
2431 2432 2433 2434 |
# File 'lib/xlsxrb.rb', line 2431 def properties(core: nil, app: nil) core&.each { |k, v| core_property(k, v) } app&.each { |k, v| app_property(k, v) } end |
#protect_sheet(**opts) ⇒ Object
: (**String | Integer | bool | nil opts) -> void
2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 |
# File 'lib/xlsxrb.rb', line 2291 def protect_sheet(**opts) sheet if @current_sheet.nil? normalized = opts.dup plain_password = normalized[:password] needs_hash = plain_password.is_a?(String) && !plain_password.empty? && normalized[:algorithm_name].nil? && normalized[:hash_value].nil? && normalized[:salt_value].nil? && normalized[:spin_count].nil? && !plain_password.match?(/\A[0-9A-Fa-f]{4}\z/) if needs_hash normalized.delete(:password) normalized.merge!(Xlsxrb::Ooxml::Utils.hash_password(plain_password)) end @current_sheet_protection = normalized end |
#protect_workbook(**opts) ⇒ void
This method returns an undefined value.
Set workbook protection.
: (**String | Integer | bool | nil opts) -> void
2401 2402 2403 |
# File 'lib/xlsxrb.rb', line 2401 def protect_workbook(**opts) @workbook_protection = opts end |
#row(values, styles: nil, height: nil, hidden: false, custom_height: false, outline_level: nil) ⇒ void
Excel's column limit is 16,384, row limit is 1,048,576, string max length is 32,767.
This method returns an undefined value.
Add a row of values. values is an Array.
- styles
Hash mapping column indices to style names, or Array of style names for each column
Add a row to the sheet.
: (Array[String | Numeric | bool | nil] | Hash[Integer | String, String | Numeric | bool | nil] values, ?styles: String | Hash[Symbol, String | Integer | bool | nil] | Array[String | Hash[Symbol, String | Integer | bool | nil] | nil] | nil, ?height: Float | Integer | nil, ?hidden: bool, ?custom_height: bool, ?outline_level: Integer | nil) -> void
1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 |
# File 'lib/xlsxrb.rb', line 1983 def row(values, styles: nil, height: nil, hidden: false, custom_height: false, outline_level: nil) sheet if @current_sheet.nil? row_index = @current_row_index # See: https://support.microsoft.com/en-us/office/excel-specifications-and-limits-1672b34d-7043-467e-8e27-269d656771c3 if @strict_excel_mode raise ArgumentError, "Row index #{row_index} exceeds Excel limit of 1,048,576 rows" if row_index >= 1_048_576 raise ArgumentError, "Row height #{height} must be between 0 and 409 points (Excel limitation)" if height && (height.negative? || height > 409) end @current_row_index += 1 if values.is_a?(Hash) max_col = values.keys.map { |k| Elements::Cell.column_index(k) }.max || -1 cells_array = Array.new(max_col + 1) values.each do |k, v| idx = Elements::Cell.column_index(k) cells_array[idx] = v end values = cells_array end if styles.is_a?(Hash) = {} styles.each do |k, v| if k.is_a?(Range) || k.is_a?(Array) k.each { |idx| [Elements::Cell.column_index(idx)] = v } else [Elements::Cell.column_index(k)] = v end end max_col_style = .keys.max || -1 styles_array = Array.new(max_col_style + 1) .each do |idx, v| styles_array[idx] = v end styles = styles_array end # Auto-detect Date / Time for built-in styles values.each_with_index do |val, idx| cell_style = styles.is_a?(Array) ? styles[idx] : styles if val.is_a?(Date) && cell_style.nil? style("__xlsxrb_date", number_format: "yyyy-mm-dd") unless @styles.key?("__xlsxrb_date") styles = [] if styles.nil? styles = Array.new(values.size, styles) unless styles.is_a?(Array) styles[idx] = "__xlsxrb_date" elsif val.is_a?(Time) && cell_style.nil? style("__xlsxrb_time", number_format: "yyyy-mm-dd hh:mm:ss") unless @styles.key?("__xlsxrb_time") styles = [] if styles.nil? styles = Array.new(values.size, styles) unless styles.is_a?(Array) styles[idx] = "__xlsxrb_time" end end @current_cells ||= {} row_num = row_index + 1 max_len = values.size max_len = [max_len, styles.size].max if styles.is_a?(Array) # See: https://support.microsoft.com/en-us/office/excel-specifications-and-limits-1672b34d-7043-467e-8e27-269d656771c3 raise ArgumentError, "Row contains #{max_len} columns, exceeding Excel limit of 16_384 columns" if @strict_excel_mode && max_len > 16_384 max_len.times do |col_idx| val = col_idx < values.size ? values[col_idx] : nil next if val.nil? raise ArgumentError, "Invalid cell value type or value: #{val.class} for value #{val.inspect}" unless val.nil? || val.is_a?(String) || (val.is_a?(Numeric) && !(val.is_a?(Float) && (val.infinite? || val.nan?))) || val.is_a?(TrueClass) || val.is_a?(FalseClass) || val.is_a?(Date) || val.is_a?(Time) || val.is_a?(Elements::Formula) || (val.is_a?(Hash) && val.key?(:formula)) || val.is_a?(Elements::RichText) || val.is_a?(Elements::CellError) # See: https://support.microsoft.com/en-us/office/excel-specifications-and-limits-1672b34d-7043-467e-8e27-269d656771c3 raise ArgumentError, "Cell text length #{val.length} exceeds Excel limit of 32,767 characters" if @strict_excel_mode && val.is_a?(String) && val.length > 32_767 addr = "#{Elements::Cell.column_letter(col_idx)}#{row_num}" @current_cells[addr] = val end attrs = nil if height || hidden || outline_level attrs = {} attrs[:height] = height if height attrs[:hidden] = true if hidden attrs[:custom_height] = custom_height || !height.nil? attrs[:outline_level] = outline_level if outline_level end @current_row_writer.write_row_values(row_index, values, styles: styles, style_map: @style_name_to_id, sst: @sst, sst_index: @sst_index, attrs: attrs) end |
#select_cell(active_cell, sqref: nil, pane: nil) ⇒ Object
: (String active_cell, ?sqref: String?, ?pane: String?) -> void
2256 2257 2258 2259 2260 |
# File 'lib/xlsxrb.rb', line 2256 def select_cell(active_cell, sqref: nil, pane: nil) sheet if @current_sheet.nil? @current_selection = { active_cell: active_cell, sqref: sqref || active_cell } @current_selection[:pane] = pane if pane end |
#shape(preset: "rect", text: nil, from_col: 0, from_row: 0, to_col: 5, to_row: 5, **opts) ⇒ Object
: (?preset: ::String, ?text: String?, ?from_col: ::Integer, ?from_row: ::Integer, ?to_col: ::Integer, ?to_row: ::Integer, **String | Integer | bool | nil opts) -> void
2319 2320 2321 2322 2323 2324 2325 |
# File 'lib/xlsxrb.rb', line 2319 def shape(preset: "rect", text: nil, from_col: 0, from_row: 0, to_col: 5, to_row: 5, **opts) sheet if @current_sheet.nil? shape = { preset: preset, text: text, from_col: from_col, from_row: from_row, to_col: to_col, to_row: to_row } shape[:name] = opts.delete(:name) || "Shape #{@current_shapes.size + 1}" shape.merge!(opts) @current_shapes << shape end |
#sheet(name = nil, **opts) {|sheet_builder| ... } ⇒ void
This method returns an undefined value.
Add a new sheet.
: (?String? name, **String | Integer | bool | nil opts) ?{ (WorksheetProxy) -> void } -> void
1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 |
# File 'lib/xlsxrb.rb', line 1910 def sheet(name = nil, **opts) name ||= "Sheet#{@sheets.size + 1}" raise ArgumentError, "Sheet name '#{name}' must be <= 31 characters (Excel limitation)" if @strict_excel_mode && name.length > 31 raise ArgumentError, "Sheet name '#{name}' contains invalid characters (ECMA-376 OOXML specification)" if name.match?(%r{[\[\]*?/\\]}) raise ArgumentError, "Sheet name '#{name}' is already used. Excel requires unique sheet names." if @strict_excel_mode && @sheets.map { |s| s.respond_to?(:name) ? s.name.downcase : s.to_s.downcase }.include?(name.downcase) internal_sheet_setup(name) opts.each { |k, v| set_sheet_property(k, v) } yield WorksheetProxy.new(self, @current_sheet) if block_given? @current_sheet end |
#sheet_properties(name, value) ⇒ Object
: (Symbol name, String | Integer | bool | Float value) -> void
2330 2331 2332 2333 |
# File 'lib/xlsxrb.rb', line 2330 def sheet_properties(name, value) sheet if @current_sheet.nil? @current_sheet_properties[name] = value end |
#sheet_view(name, value) ⇒ Object
: (Symbol name, String | Integer | bool | Float value) -> void
2336 2337 2338 2339 |
# File 'lib/xlsxrb.rb', line 2336 def sheet_view(name, value) sheet if @current_sheet.nil? @current_sheet_view[name] = value end |
#sort_state(ref, sort_conditions, **opts) ⇒ Object
: (String ref, Array[String | Hash[Symbol, String | Integer | bool | nil]] sort_conditions, **String | Integer | bool | nil opts) -> void
2141 2142 2143 2144 |
# File 'lib/xlsxrb.rb', line 2141 def sort_state(ref, sort_conditions, **opts) sheet if @current_sheet.nil? @current_sort_state = { ref: ref, sort_conditions: sort_conditions }.merge(opts) end |
#sparkline_group(sparklines:, type: nil, **opts) ⇒ Object
: (sparklines: Array, ?type: String?, **String | Integer | bool | nil opts) -> void
2200 2201 2202 2203 2204 2205 2206 |
# File 'lib/xlsxrb.rb', line 2200 def sparkline_group(sparklines:, type: nil, **opts) sheet if @current_sheet.nil? group = { sparklines: sparklines } group[:type] = type if type group.merge!(opts) @current_sparkline_groups << group end |
#split_pane(x_split: 0, y_split: 0, top_left_cell: nil) ⇒ Object
: (?x_split: ::Integer, ?y_split: ::Integer, ?top_left_cell: String?) -> void
2250 2251 2252 2253 |
# File 'lib/xlsxrb.rb', line 2250 def split_pane(x_split: 0, y_split: 0, top_left_cell: nil) sheet if @current_sheet.nil? @current_split_pane = { x_split: x_split, y_split: y_split, top_left_cell: top_left_cell } end |
#style(name, **opts) {|style_builder| ... } ⇒ StyleBuilder
Define a named style that can be applied to cells.
: (String name, **String | Integer | bool | nil opts) ?{ (WorksheetBuilder) -> void } -> void
1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 |
# File 'lib/xlsxrb.rb', line 1522 def style(name, **opts) style_builder = StyleBuilder.new(name) style_builder.(**opts) unless opts.empty? yield style_builder if block_given? @styles[name] = style_builder # Register immediately @style_name_to_id[name] = style_builder.register_with(@style_writer) style_builder end |
#table(ref, columns:, name: nil, display_name: nil, style: nil, **opts) ⇒ Object
: (String ref, columns: Array[String | Hash[Symbol, String | Integer | bool | nil]], ?name: String?, ?display_name: String?, ?style: String?, **String | Integer | bool | nil opts) -> void
2165 2166 2167 2168 2169 2170 2171 2172 2173 |
# File 'lib/xlsxrb.rb', line 2165 def table(ref, columns:, name: nil, display_name: nil, style: nil, **opts) sheet if @current_sheet.nil? tbl = { ref: ref, columns: columns } tbl[:name] = name if name tbl[:display_name] = display_name if display_name tbl[:style] = style if style tbl.merge!(opts) @current_tables << tbl end |
#validate_data(sqref, **opts) ⇒ Object
: (String sqref, **String | Integer | bool | nil opts) -> void
2149 2150 2151 2152 |
# File 'lib/xlsxrb.rb', line 2149 def validate_data(sqref, **opts) sheet if @current_sheet.nil? @current_data_validations << opts.merge(sqref: sqref) end |
#workbook_property(name, value) ⇒ void
SECURITY WARNING: If you set :update_links to anything other than "never",
you may expose end-users to malicious external reference vulnerabilities (e.g., CSV/DDE Injection)
when they open the generated Excel file. Ensure you fully trust the exported data.
This method returns an undefined value.
Set a workbook property.
: (Symbol name, String | Integer | bool value) -> void
1510 1511 1512 |
# File 'lib/xlsxrb.rb', line 1510 def workbook_property(name, value) @workbook_properties[name] = value end |