summaryrefslogtreecommitdiffstats
path: root/lib/roo/formatters
diff options
context:
space:
mode:
Diffstat (limited to 'lib/roo/formatters')
-rw-r--r--lib/roo/formatters/base.rb15
-rw-r--r--lib/roo/formatters/csv.rb84
-rw-r--r--lib/roo/formatters/matrix.rb23
-rw-r--r--lib/roo/formatters/xml.rb31
-rw-r--r--lib/roo/formatters/yaml.rb40
5 files changed, 193 insertions, 0 deletions
diff --git a/lib/roo/formatters/base.rb b/lib/roo/formatters/base.rb
new file mode 100644
index 0000000..2d32d6d
--- /dev/null
+++ b/lib/roo/formatters/base.rb
@@ -0,0 +1,15 @@
+module Roo
+ module Formatters
+ module Base
+ # converts an integer value to a time string like '02:05:06'
+ def integer_to_timestring(content)
+ h = (content / 3600.0).floor
+ content -= h * 3600
+ m = (content / 60.0).floor
+ content -= m * 60
+ s = content
+ Kernel.format("%02d:%02d:%02d", h, m, s)
+ end
+ end
+ end
+end
diff --git a/lib/roo/formatters/csv.rb b/lib/roo/formatters/csv.rb
new file mode 100644
index 0000000..3181f09
--- /dev/null
+++ b/lib/roo/formatters/csv.rb
@@ -0,0 +1,84 @@
+module Roo
+ module Formatters
+ module CSV
+ def to_csv(filename = nil, separator = ",", sheet = default_sheet)
+ if filename
+ File.open(filename, "w") do |file|
+ write_csv_content(file, sheet, separator)
+ end
+ true
+ else
+ sio = ::StringIO.new
+ write_csv_content(sio, sheet, separator)
+ sio.rewind
+ sio.read
+ end
+ end
+
+ private
+
+ # Write all cells to the csv file. File can be a filename or nil. If the
+ # file argument is nil the output goes to STDOUT
+ def write_csv_content(file = nil, sheet = nil, separator = ",")
+ file ||= STDOUT
+ return unless first_row(sheet) # The sheet is empty
+
+ 1.upto(last_row(sheet)) do |row|
+ 1.upto(last_column(sheet)) do |col|
+ # TODO: use CSV.generate_line
+ file.print(separator) if col > 1
+ file.print cell_to_csv(row, col, sheet)
+ end
+ file.print("\n")
+ end
+ end
+
+ # The content of a cell in the csv output
+ def cell_to_csv(row, col, sheet)
+ return "" if empty?(row, col, sheet)
+
+ onecell = cell(row, col, sheet)
+
+ case celltype(row, col, sheet)
+ when :string
+ %("#{onecell.gsub('"', '""')}") unless onecell.empty?
+ when :boolean
+ # TODO: this only works for excelx
+ onecell = self.sheet_for(sheet).cells[[row, col]].formatted_value
+ %("#{onecell.gsub('"', '""').downcase}")
+ when :float, :percentage
+ if onecell == onecell.to_i
+ onecell.to_i.to_s
+ else
+ onecell.to_s
+ end
+ when :formula
+ case onecell
+ when String
+ %("#{onecell.gsub('"', '""')}") unless onecell.empty?
+ when Integer
+ onecell.to_s
+ when Float
+ if onecell == onecell.to_i
+ onecell.to_i.to_s
+ else
+ onecell.to_s
+ end
+ when Date, DateTime, TrueClass, FalseClass
+ onecell.to_s
+ else
+ fail "unhandled onecell-class #{onecell.class}"
+ end
+ when :date, :datetime
+ onecell.to_s
+ when :time
+ integer_to_timestring(onecell)
+ when :link
+ %("#{onecell.url.gsub('"', '""')}")
+ else
+ fail "unhandled celltype #{celltype(row, col, sheet)}"
+ end || ""
+ end
+ end
+ end
+end
diff --git a/lib/roo/formatters/matrix.rb b/lib/roo/formatters/matrix.rb
new file mode 100644
index 0000000..39c7381
--- /dev/null
+++ b/lib/roo/formatters/matrix.rb
@@ -0,0 +1,23 @@
+module Roo
+ module Formatters
+ module Matrix
+ # returns a matrix object from the whole sheet or a rectangular area of a sheet
+ def to_matrix(from_row = nil, from_column = nil, to_row = nil, to_column = nil, sheet = default_sheet)
+ require 'matrix'
+
+ return ::Matrix.empty unless first_row
+
+ from_row ||= first_row(sheet)
+ to_row ||= last_row(sheet)
+ from_column ||= first_column(sheet)
+ to_column ||= last_column(sheet)
+
+ ::Matrix.rows(from_row.upto(to_row).map do |row|
+ from_column.upto(to_column).map do |col|
+ cell(row, col, sheet)
+ end
+ end)
+ end
+ end
+ end
+end
diff --git a/lib/roo/formatters/xml.rb b/lib/roo/formatters/xml.rb
new file mode 100644
index 0000000..ebb8cde
--- /dev/null
+++ b/lib/roo/formatters/xml.rb
@@ -0,0 +1,31 @@
+# returns an XML representation of all sheets of a spreadsheet file
+module Roo
+ module Formatters
+ module XML
+ def to_xml
+ Nokogiri::XML::Builder.new do |xml|
+ xml.spreadsheet do
+ sheets.each do |sheet|
+ self.default_sheet = sheet
+ xml.sheet(name: sheet) do |x|
+ if first_row && last_row && first_column && last_column
+ # sonst gibt es Fehler bei leeren Blaettern
+ first_row.upto(last_row) do |row|
+ first_column.upto(last_column) do |col|
+ next if empty?(row, col)
+
+ x.cell(cell(row, col),
+ row: row,
+ column: col,
+ type: celltype(row, col))
+ end
+ end
+ end
+ end
+ end
+ end
+ end.to_xml
+ end
+ end
+ end
+end
diff --git a/lib/roo/formatters/yaml.rb b/lib/roo/formatters/yaml.rb
new file mode 100644
index 0000000..69ef3ab
--- /dev/null
+++ b/lib/roo/formatters/yaml.rb
@@ -0,0 +1,40 @@
+module Roo
+ module Formatters
+ module YAML
+ # returns a rectangular area (default: all cells) as yaml-output
+ # you can add additional attributes with the prefix parameter like:
+ # oo.to_yaml({"file"=>"flightdata_2007-06-26", "sheet" => "1"})
+ def to_yaml(prefix = {}, from_row = nil, from_column = nil, to_row = nil, to_column = nil, sheet = default_sheet)
+ # return an empty string if there is no first_row, i.e. the sheet is empty
+ return "" unless first_row
+
+ from_row ||= first_row(sheet)
+ to_row ||= last_row(sheet)
+ from_column ||= first_column(sheet)
+ to_column ||= last_column(sheet)
+
+ result = "--- \n"
+ from_row.upto(to_row) do |row|
+ from_column.upto(to_column) do |col|
+ next if empty?(row, col, sheet)
+
+ result << "cell_#{row}_#{col}: \n"
+ prefix.each do|k, v|
+ result << " #{k}: #{v} \n"
+ end
+ result << " row: #{row} \n"
+ result << " col: #{col} \n"
+ result << " celltype: #{celltype(row, col, sheet)} \n"
+ value = cell(row, col, sheet)
+ if celltype(row, col, sheet) == :time
+ value = integer_to_timestring(value)
+ end
+ result << " value: #{value} \n"
+ end
+ end
+
+ result
+ end
+ end
+ end
+end