{"id":14955912,"url":"https://github.com/westonganger/rodf","last_synced_at":"2025-11-17T03:17:38.259Z","repository":{"id":452767,"uuid":"76150","full_name":"westonganger/rodf","owner":"westonganger","description":"ODF generation library for Ruby","archived":false,"fork":false,"pushed_at":"2024-12-31T08:17:25.000Z","size":362,"stargazers_count":53,"open_issues_count":3,"forks_count":15,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-11T01:34:21.224Z","etag":null,"topics":["export","odf","ods","opendocument","opendocument-spreadsheet","rails","ruby","spreadsheet"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/westonganger.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2008-11-14T21:17:33.000Z","updated_at":"2024-12-30T22:58:21.000Z","dependencies_parsed_at":"2024-06-18T18:13:58.438Z","dependency_job_id":"e43615b9-47e4-4411-8817-191cdb9ecefb","html_url":"https://github.com/westonganger/rodf","commit_stats":{"total_commits":262,"total_committers":19,"mean_commits":"13.789473684210526","dds":0.3129770992366412,"last_synced_commit":"c072f9eac4b2a663d03415e939c466f2e2099b68"},"previous_names":["thiagoarrais/rodf"],"tags_count":16,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/westonganger%2Frodf","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/westonganger%2Frodf/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/westonganger%2Frodf/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/westonganger%2Frodf/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/westonganger","download_url":"https://codeload.github.com/westonganger/rodf/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248596942,"owners_count":21130789,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["export","odf","ods","opendocument","opendocument-spreadsheet","rails","ruby","spreadsheet"],"created_at":"2024-09-24T13:11:59.495Z","updated_at":"2025-11-17T03:17:38.223Z","avatar_url":"https://github.com/westonganger.png","language":"Ruby","readme":"# RODF\n\u003ca href=\"https://badge.fury.io/rb/rodf\" target=\"_blank\"\u003e\u003cimg height=\"21\" style='border:0px;height:21px;' border='0' src=\"https://badge.fury.io/rb/rodf.svg\" alt=\"Gem Version\"\u003e\u003c/a\u003e\n\u003ca href='https://github.com/westonganger/rodf/actions' target='_blank'\u003e\u003cimg src=\"https://github.com/westonganger/rodf/actions/workflows/test.yml/badge.svg?branch=master\" style=\"max-width:100%;\" height='21' style='border:0px;height:21px;' border='0' alt=\"CI Status\"\u003e\u003c/a\u003e\n\u003ca href='https://rubygems.org/gems/rodf' target='_blank'\u003e\u003cimg height='21' style='border:0px;height:21px;' src='https://img.shields.io/gem/dt/rodf?color=brightgreen\u0026label=Rubygems%20Downloads' border='0' alt='RubyGems Downloads' /\u003e\u003c/a\u003e\n\u003ca href='https://ko-fi.com/A5071NK' target='_blank'\u003e\u003cimg height='22' style='border:0px;height:22px;' src='https://az743702.vo.msecnd.net/cdn/kofi1.png?v=a' border='0' alt='Buy Me a Coffee' /\u003e\u003c/a\u003e\n\nRODF is a library for writing to ODF output from Ruby. It mainly focuses creating ODS spreadsheets.\n\nAs 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.\n\n## Install\n\n```\ngem install rodf\n```\n\n## Usage\n\nRODF works pretty much like Builder, but with ODF-aware constructs. For example:\n\n```ruby\nRODF::Spreadsheet.file(\"my-spreadsheet.ods\") do\n  table 'My first table from Ruby' do\n    row do\n      cell 'Hello world!'\n    end\n  end\nend\n```\n\nFor access to variables and methods from outer code you can use block parameter:\n\n```ruby\n@data = 'Hello world!'\n\nRODF::Spreadsheet.file(\"my-spreadsheet.ods\") do |sheet|\n  sheet.table 'My first table from Ruby' do |table|\n    table.row do |row|\n      row.cell @data\n    end\n  end\nend\n```\n\nAdding many rows or cells at once is supported as well:\n\n```ruby\nRODF::Spreadsheet.file(\"my-spreadsheet.ods\") do |sheet|\n  sheet.table 'My first table from Ruby' do |t|\n    t.add_rows([\n      [1, 'Alice'],\n      [2, { value: 'Bob', color: '#ff0000'}],\n      [3, 'Carol']\n    ])\n\n    t.row do |r|\n      r.add_cells ['ID', 'Name']\n    end\n  end\nend\n```\n\n## Procedural style\n\nThe declarative style shown above is just syntatic sugar. A more procedural style can also be used. Like so:\n\n```ruby\nss = RODF::Spreadsheet.new\n\nt = ss.table 'My first table from Ruby'\nr = t.row\nc = r.cell 'Hello world!'\n\n# two methods to write to file\nss.write_to 'my-spreadsheet.ods'\n# or\nFile.write('my-spreadsheet.ods', ss.bytes) # you can send your data in Rails over HTTP using the bytes method\n```\n\nBoth styles can be mixed and matched at will:\n\n```ruby\nss = RODF::Spreadsheet.new\n\nss.table 'My first table from Ruby' do |t|\n  t.row do |r|\n    r.cell 'Hello world!'\n  end\nend\n\nss.write_to 'my-spreadsheet.ods'\n```\n\n## Styling and Formatting\n\n```ruby\nRODF::Spreadsheet.file(\"my-spreadsheet.ods\") do |sheet|\n\n  sheet.style 'red-cell', family: :cell do |s|\n    s.property :text, 'font-weight' =\u003e 'bold', 'color' =\u003e '#ff0000'\n  end\n\n  sheet.style 'row-height', family: :row do |s|\n    s.property :row, 'row-height' =\u003e '18pt', 'use-optimal-row-height' =\u003e 'true'\n  end\n\n  sheet.table 'Red text table' do |t|\n    t.row style: 'row-height' do |r|\n      r.cell 'Red', style: 'red-cell'\n    end\n  end\n\n  sheet.table 'Text with Paragraphs' do |t|\n    t.row style: 'row-height' do |r|\n      r.cell do |cell|\n        cell.paragraph do |paragraph|\n          text_array = my_text_content.split(\"\\n\").select{|x| !x.empty? }\n\n          text_array.each do |str|\n            if str.start_with?(\"#\")\n              paragraph.span(str, style: 'red-cell')\n            else\n              paragraph.span(str)\n            end\n          end\n        end\n      end\n    end\n  end\n\nend\n```\n\nConditional formatting is also possible:\n\n```ruby\nRODF::Spreadsheet.file(\"my-spreadsheet.ods\") do |sheet|\n\n  sheet.office_style 'red-cell', family: :cell do |s|\n    s.property :text, 'font-weight' =\u003e 'bold', 'color' =\u003e '#ff0000'\n  end\n\n  sheet.office_style 'green-cell', family: :cell do |s|\n    s.property :text, 'font-weight' =\u003e 'bold', 'color' =\u003e '#00ff00'\n  end\n\n  # conditional formating must be defined as style and the value of\n  # apply-style-name must be an office_style\n  sheet.style 'cond1', family: :cell do |s|\n    s.property :conditional, 'condition' =\u003e 'cell-content()\u003c0', 'apply-style-name' =\u003e 'red-cell'\n\n    s.property :conditional, 'condition' =\u003e 'cell-content()\u003e0', 'apply-style-name' =\u003e 'green-cell'\n  end\n\n  sheet.table 'Red text table' do |t|\n    t.row do |r|\n      r.cell 'Red force', style: 'red-cell'\n    end\n    t.row do |r|\n      r.cell '-4', type: :float, style: 'cond1'\n    end\n    t.row do |r|\n      r.cell '0', type: :float, style: 'cond1'\n    end\n    t.row do |r|\n      r.cell '5', type: :float, style: 'cond1'\n    end\n  end\nend\n```\n\n## Changing Columns Widths\n\nAdding columns or columns width to your spreadsheet can be done with the following\n\n```ruby\nRODF::Spreadsheet.file(\"my-spreadsheet.ods\") do |sheet|\n  sheet.table \"foo\" do |t|\n    sheet.style('default-col-width', family: :column) do |s|\n      s.property(:column, 'column-width' =\u003e '1.234in')\n    end\n\n    col_count.times do\n      t.column style: 'default-col-width'\n    end\n\n    ### OR\n\n    ### Warning this will overwrite any existing table columns (cells remain unaffected)\n    sheet.set_column_widths(\n      table: t, \n      column_widths: [\n        {'column-width' =\u003e '1in'},\n        {'column-width' =\u003e '2cm'},\n        {'column-width' =\u003e '2.54cm'},\n      ],\n    )\n  end\nend\n```\n\n## Columns Types\n\nAvailable columns types are:\n\n- :string\n- :float\n- :date\n- :time\n- :currency\n- :percentage\n\n## Style List\n```ruby\n### family: :cell or \"table-cell\"\nstyle \"my-cell-style\", family: :cell do\n  property :text,\n    'font-weight' =\u003e :bold, #options are :bold, :thin\n    'font-size' =\u003e 12,\n    'font-name' =\u003e 'Arial',\n    'font-style' =\u003e 'italic',\n    'text-underline-style' =\u003e 'solid', # solid, dashed, dotted, double\n    'text-underline-type' =\u003e 'single',\n    'text-line-through-style' =\u003e 'solid',\n    align: true,\n    color: \"#000000\"\n\n  property :cell,\n    'background-color' =\u003e \"#DDDDDD\",\n    'wrap-option' =\u003e 'wrap',\n    'vertical_align' =\u003e 'automatic',\n    'border-top' =\u003e '0.75pt solid #999999',\n    'border-bottom' =\u003e '0.75pt solid #999999',\n    'border-left' =\u003e '0.75pt solid #999999',\n    'border-right' =\u003e '0.75pt solid #999999',\n    'writing-mode' =\u003e 'lr-tb',\n\nend\n\n### family: :column or \"table-column\"\nstyle('my-col-style', family: :column) do\n  property :column,\n    'column-width' =\u003e '4.0cm'\nend\n\n### family: :row or \"table-row\"\nstyle('my-row-style', family: :row) do\n  property :row,\n    'row-height' =\u003e '18pt',\n    'use-optimal-row-height' =\u003e 'true'\nend\n\n### family: :table\nstyle('my-row-style', family: :table) do\n  property :table,\n    'writing-mode' =\u003e 'lr-tb',\n```\n\n## Adding Arbitrary XML Attributes\n\n```ruby\nRODF::Spreadsheet.file(\"my-spreadsheet.ods\") do |sheet|\n  sheet.table 'My first table from Ruby', attributes: {'table-protected' =\u003e 'true'} do |table|\n    table.row do |row|\n      row.cell @data\n    end\n  end\nend\n\n```\n\n## Production Usage Examples\n\n- `spreadsheet_architect` gem - [View Relevant Source Code](https://github.com/westonganger/spreadsheet_architect/blob/master/lib/spreadsheet_architect/class_methods/ods.rb)\n\n## Credits\n\nOriginally Created by [@thiagoarrais](https://github.com/thiagoarrais)\n\nMaintained by [@westonganger](https://github.com/westonganger) since 2016, for simplified ODS spreadsheet creation within the [spreadsheet_architect](https://github.com/westonganger/spreadsheet_architect) gem\n","funding_links":["https://ko-fi.com/A5071NK'"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwestonganger%2Frodf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwestonganger%2Frodf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwestonganger%2Frodf/lists"}