Module: Workbook::Readers::OdsReader

Included in:
Book
Defined in:
lib/workbook/readers/ods_reader.rb

Instance Method Summary collapse

Instance Method Details

#get_column_count(table) ⇒ Object

set column count


83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/workbook/readers/ods_reader.rb', line 83

def get_column_count(table)
  first_row = table.xpath("table:table-row").first
  cells = first_row.xpath("table:table-cell|table:covered-table-cell")
  column_count = 0
  cells.each do |cell|
    if cell.xpath('@table:number-columns-spanned').children.size>0
      column_count +=cell.xpath('@table:number-columns-spanned').children[0].inner_text.to_i
    else
      column_count +=1
    end
  end
  column_count
end

#get_repeatObject


113
114
115
116
117
118
119
# File 'lib/workbook/readers/ods_reader.rb', line 113

def get_repeat
  pre_set = @cell.xpath('@table:number-columns-repeated').to_s
  return 1 if (pre_set.nil? || pre_set=="") # if not present, don't repeat.
  return 1 unless "#{pre_set.to_i}"=="#{pre_set}" # return 1 if it's not a valid integer
  return 1 if pre_set.to_i < 1 # return 1, negative repeats make no sense
  return pre_set.to_i
end

#load_ods(file_obj) ⇒ Workbook::Book

reads self with and ods-type content.xml

Parameters:

  • file_obj (String, File)

    a file or file reference

Returns:


9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/workbook/readers/ods_reader.rb', line 9

def load_ods file_obj
  file_obj = file_obj.path if file_obj.is_a? File
  content = ""
  styles = ""
  Zip::File.open(file_obj) do |zipfile|
    zipfile.entries.each do |file|
      styles = zipfile.read(file.name) if file.name == "styles.xml"
      content = zipfile.read(file.name) if file.name == "content.xml"
    end
  end
  content = Nokogiri.XML(content)
  styles = Nokogiri.XML(styles)
  template.add_raw content
  parse_ods_style styles
  parse_ods content
  return self
end

#parse_local_cell(workbook_cell) ⇒ Object

parse the contents of a single cell


122
123
124
125
126
127
# File 'lib/workbook/readers/ods_reader.rb', line 122

def parse_local_cell(workbook_cell)
  return Workbook::NilValue.new(:covered) if @cell.name == "covered-table-cell"
  set_cell_attributes(workbook_cell)
  valuetype = @cell.xpath('@office:value-type').to_s
  parse_local_value(valuetype)
end

#parse_local_row(row) ⇒ Object

parse the contents of an entire row by parsing every cell in it and adding it to the row


98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/workbook/readers/ods_reader.rb', line 98

def parse_local_row(row)
  cells = row.xpath("table:table-cell|table:covered-table-cell")
  workbook_row = Workbook::Row.new
  cells.each do |cell|
    @cell = cell
    repeat = get_repeat
    workbook_cell = Workbook::Cell.new()
    workbook_cell.value = @cell.nil? ? nil : parse_local_cell(workbook_cell)
    repeat.times do
      workbook_row << workbook_cell
    end
  end
  return workbook_row
end

#parse_local_table(sheet, table, tableindex) ⇒ Object

parse the contents of an entire table by parsing every row in it and adding it to the table


72
73
74
75
76
77
78
79
80
# File 'lib/workbook/readers/ods_reader.rb', line 72

def parse_local_table(sheet,table,tableindex)
  local_table = sheet.create_or_open_table_at(tableindex)
  local_table.name = table.xpath("@table:name").to_s
  #column_count = get_column_count(table)
  table.xpath("table:table-row").each do |row|
    local_table << parse_local_row(row)
  end
  local_table.trim!
end

#parse_local_value(valuetype) ⇒ Object

Sets value in right context type


137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/workbook/readers/ods_reader.rb', line 137

def parse_local_value(valuetype)
  value = CGI.unescapeHTML(@cell.xpath("text:p//text()").to_s)
  value = (value=="") ? nil : value
  case valuetype
  when 'integer'
    value = @cell.xpath("@office:value").to_s.to_i
  when 'float'
    value = @cell.xpath("@office:value").to_s.to_f
    value = value.to_i unless @cell.xpath("@office:value").to_s.match(/\./) #sadly most integers are typed as floats...
  when 'date'
    value = DateTime.parse(@cell.xpath("@office:date-value").to_s)
  end
  value
end

#parse_ods(ods_spreadsheet = template.raws[Nokogiri::XML::Document], options = {}) ⇒ Workbook::Book

updates self with and ods-type content.xml

Parameters:

  • ods_spreadsheet (Nokogiri::XML::Document) (defaults to: template.raws[Nokogiri::XML::Document])

    nokogirified content.xml

Returns:


53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/workbook/readers/ods_reader.rb', line 53

def parse_ods ods_spreadsheet=template.raws[Nokogiri::XML::Document], options={}
  require 'cgi'

  options = {:additional_type_parsing=>false}.merge options
  # styles
  #puts ods_spreadsheet
  parse_ods_style ods_spreadsheet

  # data
  ods_spreadsheet.xpath("//office:body/office:spreadsheet").each_with_index do |sheet,sheetindex|
    workbook_sheet = self.create_or_open_sheet_at(sheetindex)
    sheet.xpath("table:table").each_with_index do |table,tableindex|
      parse_local_table(workbook_sheet,table,tableindex)
    end
  end
  return self
end

#parse_ods_style(parse_ods_style) ⇒ Object


32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/workbook/readers/ods_reader.rb', line 32

def parse_ods_style parse_ods_style
  parse_ods_style.xpath("//style:style").each do |style|
    style_family = style.xpath("@style:family").to_s
    if style_family == "table-cell"
      format = Workbook::Format.new
      format.name = style.xpath("@style:name").to_s
      format.parent = self.template.formats[style.xpath("@style:parent-style-name").to_s]
      set_format_property format, :border, style.xpath("style:table-cell-properties/@fo:border").to_s
      set_format_property format, :vertical_align, style.xpath("style:table-cell-properties/@style:vertical-align").to_s.gsub("automatic","auto")
      set_format_property format, :padding, style.xpath("style:table-cell-properties/@fo:padding").to_s.gsub("automatic","auto")
      set_format_property format, :font, style.xpath("style:text-properties/style:font-name").to_s + " " + style.xpath("style:text-properties/fo:font-size").to_s + " " + style.xpath("style:text-properties/fo:font-weight").to_s
      set_format_property format, :color, style.xpath("style:text-properties/@fo:color").to_s
      set_format_property format, :background_color, style.xpath("style:table-cell-properties/@fo:background-color").to_s
      self.template.add_format(format)
    end
  end
end

#set_cell_attributes(workbook_cell) ⇒ Object

Sets cell attributes for rowspan, colspan and format


130
131
132
133
134
# File 'lib/workbook/readers/ods_reader.rb', line 130

def set_cell_attributes(workbook_cell)
  workbook_cell.format = self.template.formats[@cell.xpath('@table:style-name').to_s]
  workbook_cell.colspan= @cell.xpath('@table:number-columns-spanned').to_s
  workbook_cell.rowspan= @cell.xpath('@table:number-rows-spanned').to_s
end

#set_format_property(format, property, value) ⇒ Object


27
28
29
30
# File 'lib/workbook/readers/ods_reader.rb', line 27

def set_format_property format, property, value
  value.strip!
  format[property] = value if value and value != ""
end