Giter VIP home page Giter VIP logo

rodf's Introduction

RODF

Gem Version CI Status RubyGems Downloads Buy Me a Coffee

RODF is a library for writing to ODF output from Ruby. It mainly focuses creating ODS spreadsheets.

As well as writing ODS spreadsheets, this library also can write ODT text documents but it is undocumented and will require knowledge of the ODF spec. It currently does not support ODP Slide shows. Also this is NOT an ODF reading library.

Install

gem install rodf

Usage

RODF works pretty much like Builder, but with ODF-aware constructs. For example:

RODF::Spreadsheet.file("my-spreadsheet.ods") do
  table 'My first table from Ruby' do
    row do
      cell 'Hello world!'
    end
  end
end

For access to variables and methods from outer code you can use block parameter:

@data = 'Hello world!'

RODF::Spreadsheet.file("my-spreadsheet.ods") do |sheet|
  sheet.table 'My first table from Ruby' do |table|
    table.row do |row|
      row.cell @data
    end
  end
end

Adding many rows or cells at once is supported as well:

RODF::Spreadsheet.file("my-spreadsheet.ods") do |sheet|
  sheet.table 'My first table from Ruby' do |t|
    t.add_rows([
      [1, 'Alice'],
      [2, { value: 'Bob', color: '#ff0000'}],
      [3, 'Carol']
    ])

    t.row do |r|
      r.add_cells ['ID', 'Name']
    end
  end
end

Procedural style

The declarative style shown above is just syntatic sugar. A more procedural style can also be used. Like so:

ss = RODF::Spreadsheet.new

t = ss.table 'My first table from Ruby'
r = t.row
c = r.cell 'Hello world!'

# two methods to write to file
ss.write_to 'my-spreadsheet.ods'
# or
File.write('my-spreadsheet.ods', ss.bytes) # you can send your data in Rails over HTTP using the bytes method

Both styles can be mixed and matched at will:

ss = RODF::Spreadsheet.new

ss.table 'My first table from Ruby' do |t|
  t.row do |r|
    r.cell 'Hello world!'
  end
end

ss.write_to 'my-spreadsheet.ods'

Styling and Formatting

RODF::Spreadsheet.file("my-spreadsheet.ods") do |sheet|

  sheet.style 'red-cell', family: :cell do |s|
    s.property :text, 'font-weight' => 'bold', 'color' => '#ff0000'
  end

  sheet.style 'row-height', family: :row do |s|
    s.property :row, 'row-height' => '18pt', 'use-optimal-row-height' => 'true'
  end

  sheet.table 'Red text table' do |t|
    t.row style: 'row-height' do |r|
      r.cell 'Red', style: 'red-cell'
    end
  end

  sheet.table 'Text with Paragraphs' do |t|
    t.row style: 'row-height' do |r|
      r.cell do |cell|
        cell.paragraph do |paragraph|
          text_array = my_text_content.split("\n").select{|x| !x.empty? }

          text_array.each do |str|
            if str.start_with?("#")
              paragraph.span(str, style: 'red-cell')
            else
              paragraph.span(str)
            end
          end
        end
      end
    end
  end

end

Conditional formatting is also possible:

RODF::Spreadsheet.file("my-spreadsheet.ods") do |sheet|

  sheet.office_style 'red-cell', family: :cell do |s|
    s.property :text, 'font-weight' => 'bold', 'color' => '#ff0000'
  end

  sheet.office_style 'green-cell', family: :cell do |s|
    s.property :text, 'font-weight' => 'bold', 'color' => '#00ff00'
  end

  # conditional formating must be defined as style and the value of
  # apply-style-name must be an office_style
  sheet.style 'cond1', family: :cell do |s|
    s.property :conditional, 'condition' => 'cell-content()<0', 'apply-style-name' => 'red-cell'

    s.property :conditional, 'condition' => 'cell-content()>0', 'apply-style-name' => 'green-cell'
  end

  sheet.table 'Red text table' do |t|
    t.row do |r|
      r.cell 'Red force', style: 'red-cell'
    end
    t.row do |r|
      r.cell '-4', type: :float, style: 'cond1'
    end
    t.row do |r|
      r.cell '0', type: :float, style: 'cond1'
    end
    t.row do |r|
      r.cell '5', type: :float, style: 'cond1'
    end
  end
end

Changing Columns Widths

Adding columns or columns width to your spreadsheet can be done with the following

RODF::Spreadsheet.file("my-spreadsheet.ods") do |sheet|
  sheet.table "foo" do |t|
    sheet.style('default-col-width', family: :column) do |s|
      s.property(:column, 'column-width' => '1.234in')
    end

    col_count.times do
      t.column style: 'default-col-width'
    end

    ### OR

    ### Warning this will overwrite any existing table columns (cells remain unaffected)
    sheet.set_column_widths(
      table: t, 
      column_widths: [
        {'column-width' => '1in'},
        {'column-width' => '2cm'},
        {'column-width' => '2.54cm'},
      ],
    )
  end
end

Columns Types

Available columns types are:

  • :string
  • :float
  • :date
  • :time
  • :currency
  • :percentage

Style List

### family: :cell or "table-cell"
style "my-cell-style", family: :cell do
  property :text,
    'font-weight' => :bold, #options are :bold, :thin
    'font-size' => 12,
    'font-name' => 'Arial',
    'font-style' => 'italic',
    'text-underline-style' => 'solid', # solid, dashed, dotted, double
    'text-underline-type' => 'single',
    'text-line-through-style' => 'solid',
    align: true,
    color: "#000000"

  property :cell,
    'background-color' => "#DDDDDD",
    'wrap-option' => 'wrap',
    'vertical_align' => 'automatic',
    'border-top' => '0.75pt solid #999999',
    'border-bottom' => '0.75pt solid #999999',
    'border-left' => '0.75pt solid #999999',
    'border-right' => '0.75pt solid #999999',
    'writing-mode' => 'lr-tb',

end

### family: :column or "table-column"
style('my-col-style', family: :column) do
  property :column,
    'column-width' => '4.0cm'
end

### family: :row or "table-row"
style('my-row-style', family: :row) do
  property :row,
    'row-height' => '18pt',
    'use-optimal-row-height' => 'true'
end

### family: :table
style('my-row-style', family: :table) do
  property :table,
    'writing-mode' => 'lr-tb',

Adding Arbitrary XML Attributes

RODF::Spreadsheet.file("my-spreadsheet.ods") do |sheet|
  sheet.table 'My first table from Ruby', attributes: {'table-protected' => 'true'} do |table|
    table.row do |row|
      row.cell @data
    end
  end
end

Production Usage Examples

Credits

Originally Created by @thiagoarrais

Maintained by @westonganger since 2016, for simplified ODS spreadsheet creation within the spreadsheet_architect gem

rodf's People

Contributors

alexwayfer avatar antewall avatar bradleypriest avatar dc7kr avatar petergoldstein avatar schmidt avatar tenpaiyomi avatar thiagoarrais avatar westonganger avatar zakkak avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

rodf's Issues

Support more types

When trying to add a float value it does not show.

I think the cause is on line 75 of lib/odf/cell.rb you basically only allow :string

Valid office:value-types are as follows :float, :percentage, :currency, :date, :time which you can read about here: http://books.evc-cit.info/books/odbook/ch05.html

I would be interested in helping maintain this gem such as accepting PR's, adding features like this one, and releasing new versions if your willing to give me the permissions.

Problem when dealing with NIL values

When creating a cell with a value => nil, there are problems if the cell type is specified, but the value is nil.

An example is:

cell.new(nil, :type => :date)

This would create a table cell, with office:value-type="date" and office:value="", which breaks in OpenOffice, incorrectly setting the value of the cell to '0' and some date in 1899 if formatted.

Similarly, cell.new(nil, :type => :float) will create a cell with value = "", which is also not correct.

Not sure of a simple solution, since formulas can be set for cells, and the value should be set accordingly.

Explanation for styles per property type

I am finding it very difficult to style using this gem mainly due to lack of the documentation around the styling. So far I have managed to apply a bold style to a cell.

  1. How to set a cell/columns width? (and maybe how to get the cell /column to autosize?)
  2. How to set a row background color?

Loading problems with Rails 2.3.5

Hi Thiago,

Are you aware of any issues with Rails 2.3.5 and RubyGems 1.3.6?

With a new Rails application, if you add freeze the Rails gems, and add a config line in environment.rb:

config.gem "rodf", :version => '0.1.2'

Then when trying to start the application I get errors of the form:

brimstone:rodf merul$ ruby script/server 
=> Booting Mongrel
=> Rails 2.3.5 application starting on http://0.0.0.0:3000
/Users/merul/rodf/config/../vendor/rails/railties/lib/rails/gem_dependency.rb:119:Warning: Gem::Dependency#version_requirements is deprecated and will be removed on or after August 2010.  Use #requirement
/Library/Ruby/Site/1.8/rubygems.rb:220:in `activate': undefined method `map' for nil:NilClass (NoMethodError)
from /Library/Ruby/Site/1.8/rubygems.rb:246:in `activate'
from /Library/Ruby/Site/1.8/rubygems.rb:245:in `each'
from /Library/Ruby/Site/1.8/rubygems.rb:245:in `activate'
from /Library/Ruby/Site/1.8/rubygems.rb:1056:in `gem'
from /Users/merul/rodf/config/../vendor/rails/railties/lib/rails/gem_dependency.rb:73:in `add_load_paths'
from /Users/merul/rodf/config/../vendor/rails/railties/lib/initializer.rb:301:in `add_gem_load_paths'
from /Users/merul/rodf/config/../vendor/rails/railties/lib/initializer.rb:301:in `each'
from /Users/merul/rodf/config/../vendor/rails/railties/lib/initializer.rb:301:in `add_gem_load_paths'
from /Users/merul/rodf/config/../vendor/rails/railties/lib/initializer.rb:132:in `process'
from /Users/merul/rodf/config/../vendor/rails/railties/lib/initializer.rb:113:in `send'
from /Users/merul/rodf/config/../vendor/rails/railties/lib/initializer.rb:113:in `run'
from /Users/merul/rodf/config/environment.rb:9
from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `require'
from /Users/merul/rodf/vendor/rails/activesupport/lib/active_support/dependencies.rb:156:in `require'
from /Users/merul/rodf/vendor/rails/activesupport/lib/active_support/dependencies.rb:521:in `new_constants_in'
from /Users/merul/rodf/vendor/rails/activesupport/lib/active_support/dependencies.rb:156:in `require'
from /Users/merul/rodf/vendor/rails/railties/lib/commands/server.rb:84
from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `require'
from script/server:3

Allow passing arbitrary attributes to `table()`

Currently table() seems to take a title (which becomes the table:name attribute) and nothing else. It would be convenient to be able to pass other attributes (e.g. table:protected) -- ideally without them all having to be hard-coded in advance.

My current workaround is to subclass RODF::Table, override the xml method completely, and use the procedural style instead of declarative --

ss = RODF::Spreadsheet.new {  }
table = MyTableSubclass.new(
  'title', 
  additional_attributes: { 'table:protected' => 'true', }
)
ss.tables << ss_table

-- but this is clunky.

Version 0.3.1 breaks styles.xml

There seems to be an issue introduced in rodf 0.3.1 that breaks styles.xml:

Using the 0.3.1 gem with the first example mentioned in README.md I get at the end of styles.xml:

    </number:date-style>
  </office:styles>
</office:document-styles>
</office:styles> </office:document-styles>

The last row is the issue - it duplicates the closing tags. When trying to open the my-spreadsheet.ods with LibreOffice it complains about the read error in line 30 of styles.xml.

Doing a

gem uninstall rodf --version '= 0.3.1' 

and using gem 0.3 it works fine.

How to set number format for cell?

Is there a way to set the number format of a cell, for example to date? I did not manage to find documentation or an example for this, any help appreciated.

Incompatible ODS generation (float cell)

The library generates following XML for float cells:

<table:table-cell office:value-type="float" office:value="1">
</table:table-cell>

On the other hand, LibreOffice does the following:

<table:table-cell office:value-type="float" office:value="11010" calcext:value-type="float">
<text:p>11010</text:p>
</table:table-cell>

As a consequence, some libraries (like https://github.com/roo-rb/roo) fail to load such incompatible ODS.

Please add the p element inside the table-cell element.
The content might be copied from the value attribute.

I haven't checked whether the extra content is required by the ODS specification, but it will definitely improve the compatibility.

Version: 1.1.0

Using Text Styles and/or Verbatim XML

I've been using rodf for quite a while now. I often need to work with .ods files, and I find it to be a pretty great and handy gem for that. However, today I'm struggling quite a bit trying to make a specific thing work with it, and I'm wondering whether it's possible at all.

So I'm currently in the process of writing a Ruby script that reads in two different .ods files containing localized texts, then compares these texts and writes out another .ods file, containing columns "old text", "new text" and "difference". The "difference" column is supposed to receive a diff of the two texts, created with Ruby gem "differ". The idea here is that I can quickly compare two revisions of localized texts with one another and find out what exactly changed between them.

For this, I want to utilize text styles. Removed words should be displayed in red, bold, strikethrough text; added words should be displayed in green, bold text. Everything else should be normal text. However, after half a day of trial and error, I couldn't figure out how to make this work.

At first I checked the documentation for rodf to see if there's any mention of text styles at all, but that doesn't seem to be the case. Next I tried just writing out HTML containing the text styles, like so:

row.cell "<text:span text:style-name=\"added-text\">#{added_text}</text:span>"

However, this doesn't work, presumeably because rodf uses Builder::XmlMarkup under the hood, which I assume implicitly escapes any text it receives. Therefore in the output .ods file, all I get is a verbatim <text:span> attribute, which of course isn't what I need.

Next I tried looking through the rodf source files to see if I could find a workaround, but so far I wasn't very successful.

Is there any way to do this at all right now?

How to change column-width?

Sorry if the question is dumb, but i don't understand how to do this.

@Cases = get_searchresults
ss = RODF::Spreadsheet.new
ss.style 'width', family: :cell do
property :column, 'column-width' => '4.0cm'
end
t = ss.table 'Fälle'
r = t.row
r.cell 'Fallnummer', style: 'width'
r.cell 'Mitgliedsnummer', style: 'width'
r.cell 'empfangen'
r.cell 'Status'
@cases.each do |c|
r = t.row
r.cell c.casenumber
r.cell c.membernumber
r.cell c.received.strftime("%Y-%m-%d %H:%M:%S")
r.cell c.state
end
ss.write_to 'storage/searchexport.ods'
redirect_to cases_search_path

Thanks for your help!

Line break in cell

When I add value "text\nnew line" to cell I get "<text:p>text\nnew line</text:p>" in content.xml. It should be rather "<text:p>text</text:p><text:p>new line</text:p>".

Thx 4 Your work on rodf.

Number Styles

Hi

I am trying to create a number style for integers with thousands separator. I created a spreadsheet in LibreOffice Calc to see the generated xml for the style I want, and I got this:

<number:number-style style:name="N3">
  <number:number number:decimal-places="0" number:min-integer-digits="1" number:grouping="true"/>
</number:number-style>

Now I am trying to make this style in RODF. I tried it this way:

data_style 'number-with-delimiter', 'number' do
  number 'decimal-places' => '0'
end

And I get this output:

<number:number-style style:name="number-with-delimiter">
  <number:number number:style="" number:textual=""/>
</number:number-style>

Seems that the problem is that one method in style_section.rb is allowing just two attributes for the tag, which are not the ones I need:

https://github.com/thiagoarrais/rodf/blob/0e58be76e0b85aa6fb9a2d6fe5470bca99995348/lib/rodf/style_section.rb#L35-L37

Is my diagnostic correct? Would you be willing to accept a pull request to allow more attributes in the referred method?

Unable to specify config.gem in Rails applications for rodf

I normally like to ensure the deployment environments have the correct gems installed by specifying config.gem in the environment.rb file.

However, for the rodf gem this doesn't seem to work.

I gather that config.gem is deprecated in Rails 3, but I don't understand why it doesn't work for the rodf gem in Rails 2.x.x applications.

Is there a simple solution? I'm not familiar enough with the structure of a gem package to attempt to solve this.

Possible bug in singularize method.

Hi, advices? See next for debug.

$ ruby -v

ruby 1.9.3p0 (2011-10-30 revision 33570) [x86_64-linux]

$ gem list

abstract (1.0.0)
actionmailer (3.2.1, 3.2.0, 3.0.11, 3.0.9)
actionpack (3.2.1, 3.2.0, 3.0.11, 3.0.9)
activemodel (3.2.1, 3.2.0, 3.0.11, 3.0.9)
activerecord (3.2.1, 3.2.0, 3.0.11, 3.0.9)
activeresource (3.2.1, 3.2.0, 3.0.11, 3.0.9)
activesupport (3.2.1, 3.2.0, 3.0.11, 3.0.9)
acts-as-taggable-on (2.2.2, 2.1.1)
acts_as_list (0.1.5, 0.1.4)
arel (3.0.2, 3.0.0, 2.0.10)
authlogic (3.1.0)
awesome_print (1.0.2, 1.0.1)
bigdecimal (1.1.0)
builder (3.0.0, 2.1.2)
bundler (1.0.21)
cells (3.7.0)
cocaine (0.2.1, 0.2.0)
coderay (1.0.5, 0.9.8)
daemons (1.0.10)
diff-lcs (1.1.3)
dispatcher (0.0.1)
erubis (2.7.0, 2.6.6)
eventmachine (0.12.10)
execjs (1.3.0)
gem_plugin (0.2.3)
grit (2.4.1)
hike (1.2.1)
htmlentities (4.3.1)
i18n (0.6.0, 0.5.0)
io-console (0.3)
journey (1.0.3, 1.0.1)
jquery-rails (2.0.1, 1.0.19)
json (1.6.5, 1.6.3, 1.5.4)
kaminari (0.13.0)
libv8 (3.3.10.4 x86_64-linux)
mail (2.4.1, 2.2.19)
method_source (0.7.1, 0.6.7)
mime-types (1.17.2)
minitest (2.5.1)
mongrel (1.2.0.pre2)
multi_json (1.1.0, 1.0.4)
nokogiri (1.5.2)
pg (0.13.2, 0.11.0)
polyglot (0.3.3)
pry (0.9.8.2, 0.9.7.4)
pry-doc (0.3.0)
pry-rails (0.1.6, 0.0.4)
rack (1.4.1, 1.2.4)
rack-cache (1.1)
rack-mount (0.6.14)
rack-ssl (1.3.2)
rack-test (0.6.1, 0.5.7)
rails (3.2.1, 3.2.0, 3.0.11, 3.0.9)
railties (3.2.1, 3.2.0, 3.0.11, 3.0.9)
rake (0.9.2.2)
rdoc (3.12, 3.11, 3.9.4)
rodf (0.2.0)
rspec (2.8.0)
rspec-core (2.8.0)
rspec-expectations (2.8.0)
rspec-mocks (2.8.0)
rspec-rails (2.8.1)
ruby_parser (2.3.1)
rubyzip (0.9.7)
sass (3.1.15, 3.1.11)
sass-rails (3.2.4)
sexp_processor (3.0.8)
simple_form (1.5.2)
slop (2.4.4, 2.1.0)
sprockets (2.1.2)
therubyracer (0.9.10, 0.9.9)
thin (1.3.1)
thor (0.14.6)
tilt (1.3.3)
treetop (1.4.10)
tzinfo (0.3.31)
uglifier (1.2.3)
valid_attribute (1.2.0)
yard (0.7.4)

$ cat rodf.rb

#!/usr/bin/env ruby
# encoding: UTF-8
require 'rubygems'
require 'odf/spreadsheet'
require 'active_support/inflector'

ODF::Spreadsheet.file("my-spreadsheet.ods") do |spreadsheet|
  spreadsheet.table 'My first table from Ruby' do |table|
    table.row {|row|  row.cell 'Hello, rODF world!' }
  end
end

$ ruby rodf.rb

.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/rodf-0.2.0/lib/odf/container.rb:27:in `block in contains': undefined method `singularize' for "style_sections":String (NoMethodError)
  from .rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/rodf-0.2.0/lib/odf/container.rb:26:in `each'
  from .rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/rodf-0.2.0/lib/odf/container.rb:26:in `contains'
  from .rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/rodf-0.2.0/lib/odf/data_style.rb:27:in `<class:DataStyle>'
  from .rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/rodf-0.2.0/lib/odf/data_style.rb:26:in `<module:ODF>'
  from .rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/rodf-0.2.0/lib/odf/data_style.rb:25:in `<top (required)>'
  from .rbenv/versions/1.9.3-p0/lib/ruby/1.9.1/rubygems/custom_require.rb:55:in `require'
  from .rbenv/versions/1.9.3-p0/lib/ruby/1.9.1/rubygems/custom_require.rb:55:in `require'
  from .rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/rodf-0.2.0/lib/odf/spreadsheet.rb:22:in `<top (required)>'
  from .rbenv/versions/1.9.3-p0/lib/ruby/1.9.1/rubygems/custom_require.rb:59:in `require'
  from .rbenv/versions/1.9.3-p0/lib/ruby/1.9.1/rubygems/custom_require.rb:59:in `rescue in require'
  from .rbenv/versions/1.9.3-p0/lib/ruby/1.9.1/rubygems/custom_require.rb:35:in `require'
  from rodf.rb:4:in `<main>'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.