File: worksheet.rb

package info (click to toggle)
ruby-spreadsheet 1.3.4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 8,980 kB
  • sloc: ruby: 6,939; makefile: 10
file content (133 lines) | stat: -rw-r--r-- 3,463 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
require "spreadsheet/excel/offset"
require "spreadsheet/excel/row"
require "spreadsheet/worksheet"

module Spreadsheet
  module Excel
    ##
    # Excel-specific Worksheet methods. These are mostly pertinent to the Excel
    # reader, and to recording changes to the Worksheet. You should have no reason
    # to use any of these.
    class Worksheet < Spreadsheet::Worksheet
      include Spreadsheet::Excel::Offset
      offset :dimensions
      attr_reader :offset, :ole, :links, :guts, :notes
      def initialize opts = {}
        @row_addresses = nil
        super
        @offset, @ole, @reader = opts[:offset], opts[:ole], opts[:reader]
        @dimensions = nil
        @links = {}
        @guts = {}
        @notes = {}
      end

      def add_link row, column, link
        @links.store [row, column], link
      end

      def add_note row, column, note
        @notes.store [row, column], note
      end

      def column idx
        ensure_rows_read
        super
      end

      def date_base
        @workbook.date_base
      end

      def margins
        ensure_rows_read
        super
      end

      def pagesetup
        ensure_rows_read
        super
      end

      def each *args
        ensure_rows_read
        super
      end

      def ensure_rows_read
        return if @row_addresses
        @dimensions = nil
        @row_addresses = []
        @reader&.read_worksheet self, @offset
      end

      def row idx
        @rows[idx] or begin
          ensure_rows_read
          if (addr = @row_addresses[idx])
            row = @reader.read_row self, addr
            [:default_format, :height, :outline_level, :hidden].each do |key|
              row.send :"unupdated_#{key}=", addr[key]
            end
            row.worksheet = self
            row
          else
            Row.new self, idx
          end
        end
      end

      def rows
        to_a
      end

      def row_updated idx, row
        res = super
        @workbook.changes.store self, true
        @workbook.changes.store :boundsheets, true
        @changes.store idx, true
        @changes.store :dimensions, true
        res
      end

      def set_row_address idx, opts
        @offsets.store idx, opts[:row_block]
        @row_addresses[idx] = opts
      end

      def shared_string idx
        @workbook.shared_string idx
      end

      private

      ## premature optimization?
      def have_set_dimensions value, pos, len
        if @row_addresses.size < row_count
          @row_addresses.concat Array.new(row_count - @row_addresses.size)
        end
      end

      def recalculate_dimensions
        ensure_rows_read
        shorten @rows
        @dimensions = []
        @dimensions[0] = [index_of_first(@rows),
          index_of_first(@row_addresses)].compact.min || 0
        @dimensions[1] = [@rows.size, @row_addresses.size].compact.max || 0
        compact = @rows.compact
        first_rows = compact.collect { |row| row.first_used }.compact.min
        first_addrs = @row_addresses.compact.collect do |addr|
          addr[:first_used]
        end.compact.min
        @dimensions[2] = [first_rows, first_addrs].compact.min || 0
        last_rows = compact.collect { |row| row.first_unused }.max
        last_addrs = @row_addresses.compact.collect do |addr|
          addr[:first_unused]
        end.compact.max
        @dimensions[3] = [last_rows, last_addrs].compact.max || 0
        @dimensions
      end
    end
  end
end