# File lib/spreadsheet/excel/writer/n_worksheet.rb, line 244
  def write_changes reader, endpos, sst_status

    ## FIXME this is not smart solution to update outline_level.
    #        without this process, outlines in row disappear in MS Excel.       
    @worksheet.row_count.times do |i|
      if @worksheet.row(i).outline_level > 0
        @worksheet.row(i).outline_level = @worksheet.row(i).outline_level
      end
    end

    reader.seek @worksheet.offset
    blocks = row_blocks
    lastpos = reader.pos
    offsets = {}
    row_offsets = []
    changes = @worksheet.changes
    @worksheet.offsets.each do |key, pair|
      if changes.include?(key) \
        || (sst_status == :complete_update && key.is_a?(Integer))
        offsets.store pair, key
      end
    end
    ## FIXME it may be smarter to simply write all rowblocks, instead of doing a
    #        song-and-dance routine for every row...
    work = offsets.invert
    work.each do |key, (pos, len)|
      case key
      when Integer
        row_offsets.push [key, [pos, len]]
      when :dimensions
        row_offsets.push [-1, [pos, len]]
      end
    end
    row_offsets.sort!
    row_offsets.reverse!
    control = changes.size
    @worksheet.each do |row|
      key = row.idx
      if changes.include?(key) && !work.include?(key)
        row, pair = row_offsets.find do |idx, _| idx <= key end
        work.store key, pair
      end
    end
    if changes.size > control
      warn "Your Worksheet was modified while it was being written. This should not happen.\nPlease contact the author (hannes dot wyss at gmail dot com) with a sample file\nand minimal code that generates this warning. Thanks!\n"
    end
    work = work.sort_by do |key, (pos, len)|
      [pos, key.is_a?(Integer) ? key : -1]
    end
    work.each do |key, (pos, len)|
      @io.write reader.read(pos - lastpos) if pos > lastpos
      if key.is_a?(Integer)
        if block = blocks.find do |rows| rows.any? do |row| row.idx == key end end
          write_rowblock block
          blocks.delete block
        end
      else
        send "write_#{key}"
      end
      lastpos = pos + len
      reader.seek lastpos
    end

    # Necessary for outline (grouping) and hiding functions 
    # but these below are not necessary to run
    # if [Row|Column]#hidden? = false and [Row|Column]#outline_level == 0
    write_colinfos
    write_guts

    @io.write reader.read(endpos - lastpos)
  end