simple_xlsx_writer 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +20 -0
- data/README +44 -0
- data/Rakefile +40 -0
- data/lib/simple_xlsx.rb +11 -0
- data/lib/simple_xlsx/document.rb +21 -0
- data/lib/simple_xlsx/monkey_patches_for_true_zip_stream.rb +61 -0
- data/lib/simple_xlsx/serializer.rb +196 -0
- data/lib/simple_xlsx/sheet.rb +83 -0
- data/lib/simple_xlsx/xml_escape.rb +6 -0
- data/test/simple_xlsx/document_test.rb +24 -0
- data/test/simple_xlsx/sheet_test.rb +81 -0
- data/test/simple_xlsx_test.rb +29 -0
- data/test/test_helper.rb +8 -0
- metadata +113 -0
    
        data/LICENSE
    ADDED
    
    | @@ -0,0 +1,20 @@ | |
| 1 | 
            +
            Copyright (c) 2010 Dee Zsombor (zsombor@primalgrasp.com)
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            Permission is hereby granted, free of charge, to any person obtaining
         | 
| 4 | 
            +
            a copy of this software and associated documentation files (the
         | 
| 5 | 
            +
            "Software"), to deal in the Software without restriction, including
         | 
| 6 | 
            +
            without limitation the rights to use, copy, modify, merge, publish,
         | 
| 7 | 
            +
            distribute, sublicense, and/or sell copies of the Software, and to
         | 
| 8 | 
            +
            permit persons to whom the Software is furnished to do so, subject to
         | 
| 9 | 
            +
            the following conditions:
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            The above copyright notice and this permission notice shall be
         | 
| 12 | 
            +
            included in all copies or substantial portions of the Software.
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
         | 
| 15 | 
            +
            EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
         | 
| 16 | 
            +
            MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
         | 
| 17 | 
            +
            NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
         | 
| 18 | 
            +
            LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
         | 
| 19 | 
            +
            OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
         | 
| 20 | 
            +
            WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
         | 
    
        data/README
    ADDED
    
    | @@ -0,0 +1,44 @@ | |
| 1 | 
            +
            ** Description **
         | 
| 2 | 
            +
             | 
| 3 | 
            +
             | 
| 4 | 
            +
              This is a simple no fuss generator for OpenXML aka XLSX files. No
         | 
| 5 | 
            +
              formatting, styles just raw content with a few basic datatypes
         | 
| 6 | 
            +
              supported. Produced output is tested to be compatible with
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                - Open Office 3.2 series (Linux, Mac, Windows)
         | 
| 9 | 
            +
                - Neo Office 3.2 series (Mac)
         | 
| 10 | 
            +
                - Microsoft Office 2007 (Windows)
         | 
| 11 | 
            +
                - Microsoft Office 2010 (Windows)
         | 
| 12 | 
            +
                - Microsoft Office 2008 for Mac (versions 12.2.5 or above)
         | 
| 13 | 
            +
                - Microsoft Excel Viewer (Windows)
         | 
| 14 | 
            +
              
         | 
| 15 | 
            +
              Numbers of iWork '09 does not appear to support the inline string
         | 
| 16 | 
            +
              storage model prefered by this gem. Apple may release a fix for this
         | 
| 17 | 
            +
              eventually, I have avoided the more common shared string table
         | 
| 18 | 
            +
              method as it cannot be implemented in linear time.
         | 
| 19 | 
            +
             | 
| 20 | 
            +
             | 
| 21 | 
            +
            ** Sample **
         | 
| 22 | 
            +
             | 
| 23 | 
            +
             | 
| 24 | 
            +
              serializer = SimpleXlsx::Serializer.new("test.xlsx") do |doc|
         | 
| 25 | 
            +
                doc.add_sheet("People") do |sheet|
         | 
| 26 | 
            +
                  sheet.add_row(%w{DoB Name Occupation})
         | 
| 27 | 
            +
                  sheet.add_row([Date.parse("July 31, 1912"), 
         | 
| 28 | 
            +
                                 "Milton Friedman", 
         | 
| 29 | 
            +
                                 "Economist / Statistician"])
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
              end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
             | 
| 34 | 
            +
            ** License **
         | 
| 35 | 
            +
             | 
| 36 | 
            +
             | 
| 37 | 
            +
              See attached LICENSE for details.
         | 
| 38 | 
            +
             | 
| 39 | 
            +
             | 
| 40 | 
            +
            ** Credits **
         | 
| 41 | 
            +
             | 
| 42 | 
            +
             | 
| 43 | 
            +
              Written by Dee Zsombor: http://primalgrasp.com
         | 
| 44 | 
            +
              Funded by Harvest: http://www.getharvest.com
         | 
    
        data/Rakefile
    ADDED
    
    | @@ -0,0 +1,40 @@ | |
| 1 | 
            +
            require 'rubygems'
         | 
| 2 | 
            +
            require 'rake'
         | 
| 3 | 
            +
            require 'rake/testtask'
         | 
| 4 | 
            +
            require 'rake/gempackagetask'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            task :default => [:test]
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            Rake::TestTask.new do |test|
         | 
| 9 | 
            +
              test.libs       << "test"
         | 
| 10 | 
            +
              test.test_files =  Dir['test/**/*_test.rb'].sort
         | 
| 11 | 
            +
              test.verbose    =  true
         | 
| 12 | 
            +
            end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            desc "generate tags for emacs"
         | 
| 15 | 
            +
            task :tags do
         | 
| 16 | 
            +
              sh "ctags -Re lib/ "
         | 
| 17 | 
            +
            end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
             | 
| 20 | 
            +
            spec = Gem::Specification.new do |s|
         | 
| 21 | 
            +
              s.name = "simple_xlsx_writer"
         | 
| 22 | 
            +
              s.version = "0.5.3"
         | 
| 23 | 
            +
              s.author = "Dee Zsombor"
         | 
| 24 | 
            +
              s.email = "zsombor@primalgrasp.com"
         | 
| 25 | 
            +
              s.homepage = "http://simplxlsxwriter.rubyforge.org"
         | 
| 26 | 
            +
              s.rubyforge_project = "simple_xlsx_writer"
         | 
| 27 | 
            +
              s.platform = Gem::Platform::RUBY
         | 
| 28 | 
            +
              s.summary = "Just as the name says, simple writter for Office 2007+ Excel files"
         | 
| 29 | 
            +
              s.files = [FileList["{bin,lib}/**/*"].to_a, "LICENSE", "Rakefile"].flatten
         | 
| 30 | 
            +
              s.require_path = "lib"
         | 
| 31 | 
            +
              s.test_files = [FileList["{test}/**/*test.rb"].to_a, "test/test_helper.rb"].flatten
         | 
| 32 | 
            +
              s.has_rdoc = true
         | 
| 33 | 
            +
              s.extra_rdoc_files = ["README"]
         | 
| 34 | 
            +
              s.add_dependency("rubyzip", ">= 0.9.4")
         | 
| 35 | 
            +
              s.add_dependency("fast_xs", ">= 0.7.3")
         | 
| 36 | 
            +
            end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
            Rake::GemPackageTask.new(spec) do |pkg|
         | 
| 39 | 
            +
              pkg.need_tar = true
         | 
| 40 | 
            +
            end
         | 
    
        data/lib/simple_xlsx.rb
    ADDED
    
    | @@ -0,0 +1,11 @@ | |
| 1 | 
            +
            require 'tempfile'
         | 
| 2 | 
            +
            require 'rubygems'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            $:.unshift(File.dirname(__FILE__))
         | 
| 5 | 
            +
            require 'simple_xlsx/xml_escape'
         | 
| 6 | 
            +
            require 'simple_xlsx/monkey_patches_for_true_zip_stream'
         | 
| 7 | 
            +
            require 'simple_xlsx/serializer'
         | 
| 8 | 
            +
            require 'simple_xlsx/document'
         | 
| 9 | 
            +
            require 'simple_xlsx/sheet'
         | 
| 10 | 
            +
             | 
| 11 | 
            +
             | 
| @@ -0,0 +1,21 @@ | |
| 1 | 
            +
            module SimpleXlsx
         | 
| 2 | 
            +
              class Document
         | 
| 3 | 
            +
                def initialize(io)
         | 
| 4 | 
            +
                  @sheets = []
         | 
| 5 | 
            +
                  @io = io
         | 
| 6 | 
            +
                end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                attr_reader :sheets
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                def add_sheet name, &block
         | 
| 11 | 
            +
                  @io.open_stream_for_sheet(@sheets.size) do |stream|
         | 
| 12 | 
            +
                    @sheets << Sheet.new(self, name, stream, &block)
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                def has_shared_strings?
         | 
| 17 | 
            +
                  false
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
            end
         | 
| @@ -0,0 +1,61 @@ | |
| 1 | 
            +
            require 'zip/zip' #dep
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            __END__
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module Zip
         | 
| 6 | 
            +
              class ZipOutputStream
         | 
| 7 | 
            +
                def initialize(fileName)
         | 
| 8 | 
            +
                  super()
         | 
| 9 | 
            +
                  if fileName.is_a?(String) && !fileName.empty?
         | 
| 10 | 
            +
                    @fileName = fileName
         | 
| 11 | 
            +
                    @outputStream = File.new(@fileName, "wb")
         | 
| 12 | 
            +
                  else
         | 
| 13 | 
            +
                    @outputStream = fileName
         | 
| 14 | 
            +
                    @fileName = ''
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
                  @entrySet = ZipEntrySet.new
         | 
| 17 | 
            +
                  @compressor = NullCompressor.instance
         | 
| 18 | 
            +
                  @closed = false
         | 
| 19 | 
            +
                  @currentEntry = nil
         | 
| 20 | 
            +
                  @comment = nil
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
              class ZipFile < ZipCentralDirectory
         | 
| 25 | 
            +
                def initialize(stream, create = nil)
         | 
| 26 | 
            +
                  super()
         | 
| 27 | 
            +
                  @name = stream.is_a?(String) ? stream : ''
         | 
| 28 | 
            +
                  @comment = ""
         | 
| 29 | 
            +
                  if stream.is_a?(String) && File.exists?(stream)
         | 
| 30 | 
            +
                    File.open(name, "rb") { |f| read_from_stream(f) }
         | 
| 31 | 
            +
                  elsif (create)
         | 
| 32 | 
            +
                    @entrySet = ZipEntrySet.new
         | 
| 33 | 
            +
                  elsif !stream.is_a?(String) && !create && !stream.respond_to(:path)
         | 
| 34 | 
            +
                    # do nothing here
         | 
| 35 | 
            +
                  elsif !stream.is_a?(String) && !create
         | 
| 36 | 
            +
                    File.open(stream.path, "rb") { |f| read_from_stream(f) }
         | 
| 37 | 
            +
                  else
         | 
| 38 | 
            +
                    raise ZipError, "File #{stream} not found"
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
                  @create = create
         | 
| 41 | 
            +
                  @storedEntries = @entrySet.dup
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  @restore_ownership = false
         | 
| 44 | 
            +
                  @restore_permissions = false
         | 
| 45 | 
            +
                  @restore_times = true
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                def on_success_replace arg
         | 
| 49 | 
            +
                  if arg.is_a?(String) && !arg.empty?
         | 
| 50 | 
            +
                    tmpfile = get_tempfile
         | 
| 51 | 
            +
                    tmpFilename = tmpfile.path
         | 
| 52 | 
            +
                    tmpfile.close
         | 
| 53 | 
            +
                    if yield tmpFilename
         | 
| 54 | 
            +
                      File.rename(tmpFilename, name)
         | 
| 55 | 
            +
                    end
         | 
| 56 | 
            +
                  else
         | 
| 57 | 
            +
                    yield arg
         | 
| 58 | 
            +
                  end
         | 
| 59 | 
            +
                end
         | 
| 60 | 
            +
              end
         | 
| 61 | 
            +
            end
         | 
| @@ -0,0 +1,196 @@ | |
| 1 | 
            +
            module SimpleXlsx
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class Serializer
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              def initialize to
         | 
| 6 | 
            +
                @to = to
         | 
| 7 | 
            +
                Zip::ZipFile.open(to, Zip::ZipFile::CREATE) do |zip|
         | 
| 8 | 
            +
                  @zip = zip
         | 
| 9 | 
            +
                  add_doc_props
         | 
| 10 | 
            +
                  add_worksheets_directory
         | 
| 11 | 
            +
                  add_relationship_part
         | 
| 12 | 
            +
                  add_styles
         | 
| 13 | 
            +
                  @doc = Document.new(self)
         | 
| 14 | 
            +
                  yield @doc
         | 
| 15 | 
            +
                  add_workbook_relationship_part
         | 
| 16 | 
            +
                  add_content_types
         | 
| 17 | 
            +
                  add_workbook_part
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              def add_workbook_part
         | 
| 22 | 
            +
                @zip.get_output_stream "xl/workbook.xml" do |f|
         | 
| 23 | 
            +
                  f.puts <<-ends
         | 
| 24 | 
            +
            <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
         | 
| 25 | 
            +
            <workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
         | 
| 26 | 
            +
            <workbookPr date1904="0" />
         | 
| 27 | 
            +
            <sheets>
         | 
| 28 | 
            +
            ends
         | 
| 29 | 
            +
                  @doc.sheets.each_with_index do |sheet, ndx|
         | 
| 30 | 
            +
                    f.puts "<sheet name=\"#{sheet.name}\" sheetId=\"#{ndx + 1}\" r:id=\"#{sheet.rid}\"/>"
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
                  f.puts "</sheets></workbook>"
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
              def add_worksheets_directory
         | 
| 37 | 
            +
                @zip.mkdir "xl"
         | 
| 38 | 
            +
                @zip.mkdir "xl/worksheets"
         | 
| 39 | 
            +
              end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
              def open_stream_for_sheet ndx
         | 
| 42 | 
            +
                @zip.get_output_stream "xl/worksheets/sheet#{ndx + 1}.xml" do |f|
         | 
| 43 | 
            +
                  yield f
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
              def add_content_types
         | 
| 48 | 
            +
                @zip.get_output_stream "[Content_Types].xml" do |f|
         | 
| 49 | 
            +
                  f.puts '<?xml version="1.0" encoding="UTF-8"?>'
         | 
| 50 | 
            +
                  f.puts '<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">'
         | 
| 51 | 
            +
                  f.puts <<-ends
         | 
| 52 | 
            +
              <Override PartName="/_rels/.rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
         | 
| 53 | 
            +
              <Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/>
         | 
| 54 | 
            +
              <Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml"/>
         | 
| 55 | 
            +
              <Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/>
         | 
| 56 | 
            +
              <Override PartName="/xl/_rels/workbook.xml.rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
         | 
| 57 | 
            +
            ends
         | 
| 58 | 
            +
                  if @doc.has_shared_strings?
         | 
| 59 | 
            +
                    f.puts '<Override PartName="/xl/sharedStrings.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml"/>'
         | 
| 60 | 
            +
                  end
         | 
| 61 | 
            +
                  @doc.sheets.each_with_index do |sheet, ndx|
         | 
| 62 | 
            +
                    f.puts "<Override PartName=\"/xl/worksheets/sheet#{ndx+1}.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml\"/>"
         | 
| 63 | 
            +
                  end
         | 
| 64 | 
            +
                  f.puts '<Override PartName="/xl/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"/>'
         | 
| 65 | 
            +
                  f.puts "</Types>"
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
              end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
              def add_workbook_relationship_part
         | 
| 70 | 
            +
                @zip.mkdir "xl/_rels"
         | 
| 71 | 
            +
                @zip.get_output_stream "xl/_rels/workbook.xml.rels" do |f|
         | 
| 72 | 
            +
                  f.puts <<-ends
         | 
| 73 | 
            +
            <?xml version="1.0" encoding="UTF-8"?>
         | 
| 74 | 
            +
            <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
         | 
| 75 | 
            +
            ends
         | 
| 76 | 
            +
                  cnt = 0
         | 
| 77 | 
            +
                  f.puts "<Relationship Id=\"rId#{cnt += 1}\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles\" Target=\"styles.xml\"/>"
         | 
| 78 | 
            +
                  @doc.sheets.each_with_index do |sheet, ndx|
         | 
| 79 | 
            +
                    sheet.rid = "rId#{cnt += 1}"
         | 
| 80 | 
            +
                    f.puts "<Relationship Id=\"#{sheet.rid}\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet\" Target=\"worksheets/sheet#{ndx + 1}.xml\"/>"
         | 
| 81 | 
            +
                  end
         | 
| 82 | 
            +
                  if @doc.has_shared_strings?
         | 
| 83 | 
            +
                    f.puts '<Relationship Id="rId#{cnt += 1}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings" Target="xl/sharedStrings.xml"/>'
         | 
| 84 | 
            +
                  end
         | 
| 85 | 
            +
                  f.puts "</Relationships>"
         | 
| 86 | 
            +
                end
         | 
| 87 | 
            +
              end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
              def add_relationship_part
         | 
| 90 | 
            +
                @zip.mkdir "_rels"
         | 
| 91 | 
            +
                @zip.get_output_stream "_rels/.rels" do |f|
         | 
| 92 | 
            +
                  f.puts <<-ends
         | 
| 93 | 
            +
            <?xml version="1.0" encoding="UTF-8"?>
         | 
| 94 | 
            +
            <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
         | 
| 95 | 
            +
              <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/>
         | 
| 96 | 
            +
              <Relationship Id="rId2" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/>
         | 
| 97 | 
            +
              <Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml"/>
         | 
| 98 | 
            +
            ends
         | 
| 99 | 
            +
                  f.puts "</Relationships>"
         | 
| 100 | 
            +
                end
         | 
| 101 | 
            +
              end
         | 
| 102 | 
            +
             | 
| 103 | 
            +
              def add_doc_props
         | 
| 104 | 
            +
                @zip.mkdir "docProps"
         | 
| 105 | 
            +
                @zip.get_output_stream "docProps/core.xml" do |f|
         | 
| 106 | 
            +
                  f.puts <<-ends
         | 
| 107 | 
            +
            <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
         | 
| 108 | 
            +
            <cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcmitype="http://purl.org/dc/dcmitype/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
         | 
| 109 | 
            +
               <dcterms:created xsi:type="dcterms:W3CDTF">2010-07-20T14:30:58.00Z</dcterms:created>
         | 
| 110 | 
            +
               <cp:revision>0</cp:revision>
         | 
| 111 | 
            +
            </cp:coreProperties>
         | 
| 112 | 
            +
            ends
         | 
| 113 | 
            +
                end
         | 
| 114 | 
            +
                @zip.get_output_stream "docProps/app.xml" do |f|
         | 
| 115 | 
            +
                  f.puts <<-ends
         | 
| 116 | 
            +
            <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
         | 
| 117 | 
            +
            <Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties" xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes">
         | 
| 118 | 
            +
              <TotalTime>0</TotalTime>
         | 
| 119 | 
            +
            </Properties>
         | 
| 120 | 
            +
            ends
         | 
| 121 | 
            +
                end
         | 
| 122 | 
            +
              end
         | 
| 123 | 
            +
             | 
| 124 | 
            +
              def add_styles
         | 
| 125 | 
            +
                @zip.get_output_stream "xl/styles.xml" do |f|
         | 
| 126 | 
            +
                  f.puts <<-ends
         | 
| 127 | 
            +
            <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
         | 
| 128 | 
            +
            <styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
         | 
| 129 | 
            +
            <numFmts count="7">
         | 
| 130 | 
            +
              <numFmt formatCode="GENERAL" numFmtId="164"/>
         | 
| 131 | 
            +
              <numFmt formatCode=""TRUE";"TRUE";"FALSE"" numFmtId="170"/>
         | 
| 132 | 
            +
            </numFmts>
         | 
| 133 | 
            +
            <fonts count="5">
         | 
| 134 | 
            +
              <font><name val="Mangal"/><family val="2"/><sz val="10"/></font>
         | 
| 135 | 
            +
              <font><name val="Arial"/><family val="0"/><sz val="10"/></font>
         | 
| 136 | 
            +
              <font><name val="Arial"/><family val="0"/><sz val="10"/></font>
         | 
| 137 | 
            +
              <font><name val="Arial"/><family val="0"/><sz val="10"/></font>
         | 
| 138 | 
            +
              <font><name val="Arial"/><family val="2"/><sz val="10"/></font>
         | 
| 139 | 
            +
            </fonts>
         | 
| 140 | 
            +
            <fills count="2">
         | 
| 141 | 
            +
              <fill><patternFill patternType="none"/></fill>
         | 
| 142 | 
            +
              <fill><patternFill patternType="gray125"/></fill>
         | 
| 143 | 
            +
            </fills>
         | 
| 144 | 
            +
            <borders count="1">
         | 
| 145 | 
            +
              <border diagonalDown="false" diagonalUp="false"><left/><right/><top/><bottom/><diagonal/></border>
         | 
| 146 | 
            +
            </borders>
         | 
| 147 | 
            +
            <cellStyleXfs count="20">
         | 
| 148 | 
            +
              <xf applyAlignment="true" applyBorder="true" applyFont="true" applyProtection="true" borderId="0" fillId="0" fontId="0" numFmtId="164">
         | 
| 149 | 
            +
                <alignment horizontal="general" indent="0" shrinkToFit="false" textRotation="0" vertical="bottom" wrapText="false"/>
         | 
| 150 | 
            +
                <protection hidden="false" locked="true"/>
         | 
| 151 | 
            +
              </xf>
         | 
| 152 | 
            +
              <xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="1" numFmtId="0"></xf>
         | 
| 153 | 
            +
              <xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="1" numFmtId="0"></xf>
         | 
| 154 | 
            +
              <xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="2" numFmtId="0"></xf>
         | 
| 155 | 
            +
              <xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="2" numFmtId="0"></xf>
         | 
| 156 | 
            +
              <xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"></xf>
         | 
| 157 | 
            +
              <xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"></xf>
         | 
| 158 | 
            +
              <xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"></xf>
         | 
| 159 | 
            +
              <xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"></xf>
         | 
| 160 | 
            +
              <xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"></xf>
         | 
| 161 | 
            +
              <xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"></xf>
         | 
| 162 | 
            +
              <xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"></xf>
         | 
| 163 | 
            +
              <xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"></xf>
         | 
| 164 | 
            +
              <xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"></xf>
         | 
| 165 | 
            +
              <xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"></xf>
         | 
| 166 | 
            +
              <xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="1" numFmtId="43"></xf>
         | 
| 167 | 
            +
              <xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="1" numFmtId="41"></xf>
         | 
| 168 | 
            +
              <xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="1" numFmtId="44"></xf>
         | 
| 169 | 
            +
              <xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="1" numFmtId="42"></xf>
         | 
| 170 | 
            +
              <xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="1" numFmtId="9"></xf>
         | 
| 171 | 
            +
              </cellStyleXfs>
         | 
| 172 | 
            +
            <cellXfs count="7">
         | 
| 173 | 
            +
              <xf applyAlignment="false" applyBorder="false" applyFont="false" applyProtection="false" borderId="0" fillId="0" fontId="4" numFmtId="164" xfId="0"></xf>
         | 
| 174 | 
            +
              <xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="4" numFmtId="22" xfId="0"></xf>
         | 
| 175 | 
            +
              <xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="4" numFmtId="15" xfId="0"></xf>
         | 
| 176 | 
            +
              <xf applyAlignment="false" applyBorder="false" applyFont="false" applyProtection="false" borderId="0" fillId="0" fontId="4" numFmtId="1" xfId="0"></xf>
         | 
| 177 | 
            +
              <xf applyAlignment="false" applyBorder="false" applyFont="false" applyProtection="false" borderId="0" fillId="0" fontId="4" numFmtId="2" xfId="0"></xf>
         | 
| 178 | 
            +
              <xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="4" numFmtId="49" xfId="0"></xf>
         | 
| 179 | 
            +
              <xf applyAlignment="false" applyBorder="false" applyFont="false" applyProtection="false" borderId="0" fillId="0" fontId="4" numFmtId="170" xfId="0"></xf>
         | 
| 180 | 
            +
            </cellXfs>
         | 
| 181 | 
            +
            <cellStyles count="6"><cellStyle builtinId="0" customBuiltin="false" name="Normal" xfId="0"/>
         | 
| 182 | 
            +
              <cellStyle builtinId="3" customBuiltin="false" name="Comma" xfId="15"/>
         | 
| 183 | 
            +
              <cellStyle builtinId="6" customBuiltin="false" name="Comma [0]" xfId="16"/>
         | 
| 184 | 
            +
              <cellStyle builtinId="4" customBuiltin="false" name="Currency" xfId="17"/>
         | 
| 185 | 
            +
              <cellStyle builtinId="7" customBuiltin="false" name="Currency [0]" xfId="18"/>
         | 
| 186 | 
            +
              <cellStyle builtinId="5" customBuiltin="false" name="Percent" xfId="19"/>
         | 
| 187 | 
            +
            </cellStyles>
         | 
| 188 | 
            +
            </styleSheet>
         | 
| 189 | 
            +
            ends
         | 
| 190 | 
            +
                end
         | 
| 191 | 
            +
              end
         | 
| 192 | 
            +
             | 
| 193 | 
            +
            end
         | 
| 194 | 
            +
             | 
| 195 | 
            +
            end
         | 
| 196 | 
            +
             | 
| @@ -0,0 +1,83 @@ | |
| 1 | 
            +
            require 'bigdecimal'
         | 
| 2 | 
            +
            require 'time'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            module SimpleXlsx
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            class Sheet
         | 
| 7 | 
            +
              attr_reader :name
         | 
| 8 | 
            +
              attr_accessor :rid
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              def initialize document, name, stream, &block
         | 
| 11 | 
            +
                @document = document
         | 
| 12 | 
            +
                @stream =  stream
         | 
| 13 | 
            +
                @name = name
         | 
| 14 | 
            +
                @row_ndx = 1
         | 
| 15 | 
            +
                @stream.write <<-ends
         | 
| 16 | 
            +
            <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
         | 
| 17 | 
            +
            <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
         | 
| 18 | 
            +
            <sheetData>
         | 
| 19 | 
            +
            ends
         | 
| 20 | 
            +
                if block_given?
         | 
| 21 | 
            +
                  yield self
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
                @stream.write "</sheetData></worksheet>"
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
              def add_row arry
         | 
| 27 | 
            +
                row = ["<row r=\"#{@row_ndx}\">"]
         | 
| 28 | 
            +
                arry.each_with_index do |value, col_ndx|
         | 
| 29 | 
            +
                  kind, ccontent, cstyle = Sheet.format_field_and_type_and_style value
         | 
| 30 | 
            +
                  row << "<c r=\"#{Sheet.column_index(col_ndx)}#{@row_ndx}\" t=\"#{kind.to_s}\" s=\"#{cstyle}\">#{ccontent}</c>"
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
                row << "</row>"
         | 
| 33 | 
            +
                @row_ndx += 1
         | 
| 34 | 
            +
                @stream.write(row.join())
         | 
| 35 | 
            +
              end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
              def self.format_field_and_type_and_style value
         | 
| 38 | 
            +
                if value.is_a?(String)
         | 
| 39 | 
            +
                  [:inlineStr, "<is><t>#{value.to_xs}</t></is>", 5]
         | 
| 40 | 
            +
                elsif value.is_a?(BigDecimal)
         | 
| 41 | 
            +
                  [:n, "<v>#{value.to_s('f')}</v>", 4]
         | 
| 42 | 
            +
                elsif value.is_a?(Float)
         | 
| 43 | 
            +
                  [:n, "<v>#{value.to_s}</v>", 4]
         | 
| 44 | 
            +
                elsif value.is_a?(Numeric)
         | 
| 45 | 
            +
                  [:n, "<v>#{value.to_s}</v>", 3]
         | 
| 46 | 
            +
                elsif value.is_a?(Date)
         | 
| 47 | 
            +
                  [:n, "<v>#{days_since_jan_1_1900(value)}</v>", 2]
         | 
| 48 | 
            +
                elsif value.is_a?(Time)
         | 
| 49 | 
            +
                  [:n, "<v>#{fractional_days_since_jan_1_1900(value)}</v>", 1]
         | 
| 50 | 
            +
                elsif value.is_a?(TrueClass) || value.is_a?(FalseClass)
         | 
| 51 | 
            +
                  [:b, "<v>#{value ? '1' : '0'}</v>", 6]
         | 
| 52 | 
            +
                else
         | 
| 53 | 
            +
                  [:inlineStr, "<is><t>#{value.to_s.to_xs}</t></is>", 5]
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
              end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
              def self.days_since_jan_1_1900 date
         | 
| 58 | 
            +
                @@jan_1_1904 ||= Date.parse("1904 Jan 1")
         | 
| 59 | 
            +
                (date - @@jan_1_1904).to_i + 1462 # http://support.microsoft.com/kb/180162
         | 
| 60 | 
            +
              end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
              def self.fractional_days_since_jan_1_1900 value
         | 
| 63 | 
            +
                @@jan_1_1904_midnight ||= ::Time.utc(1904, 1, 1)
         | 
| 64 | 
            +
                ((value - @@jan_1_1904_midnight) / 86400.0) + #24*60*60
         | 
| 65 | 
            +
                  1462 # http://support.microsoft.com/kb/180162
         | 
| 66 | 
            +
              end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
              def self.abc
         | 
| 69 | 
            +
                @@abc ||= ('A'..'Z').to_a
         | 
| 70 | 
            +
              end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
              def self.column_index n
         | 
| 73 | 
            +
                result = []
         | 
| 74 | 
            +
                while n >= 26 do
         | 
| 75 | 
            +
                  result << abc[n % 26]
         | 
| 76 | 
            +
                  n /= 26
         | 
| 77 | 
            +
                end
         | 
| 78 | 
            +
                result << abc[result.empty? ? n : n - 1]
         | 
| 79 | 
            +
                result.reverse.join
         | 
| 80 | 
            +
              end
         | 
| 81 | 
            +
             | 
| 82 | 
            +
            end
         | 
| 83 | 
            +
            end
         | 
| @@ -0,0 +1,24 @@ | |
| 1 | 
            +
            require File.dirname(__FILE__) + '/../test_helper.rb'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module SimpleXlsx
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            class DocumentTest < Test::Unit::TestCase
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              def open_stream_for_sheet sheets_size
         | 
| 8 | 
            +
                assert_equal sheets_size, @doc.sheets.size
         | 
| 9 | 
            +
                yield self
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              def write arg
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              def test_add_sheet
         | 
| 16 | 
            +
                @doc = Document.new self
         | 
| 17 | 
            +
                assert_equal [], @doc.sheets
         | 
| 18 | 
            +
                @doc.add_sheet "new sheet"
         | 
| 19 | 
            +
                assert_equal 1, @doc.sheets.size
         | 
| 20 | 
            +
                assert_equal 'new sheet', @doc.sheets.first.name
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            end
         | 
| 24 | 
            +
            end
         | 
| @@ -0,0 +1,81 @@ | |
| 1 | 
            +
            require File.dirname(__FILE__) + '/../test_helper.rb'
         | 
| 2 | 
            +
            require "rexml/document"
         | 
| 3 | 
            +
            require 'time'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module SimpleXlsx
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            class SheetTest < Test::Unit::TestCase
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              def test_column_index
         | 
| 10 | 
            +
                assert_equal 'A', Sheet.column_index(0)
         | 
| 11 | 
            +
                assert_equal 'B', Sheet.column_index(1)
         | 
| 12 | 
            +
                assert_equal 'C', Sheet.column_index(2)
         | 
| 13 | 
            +
                assert_equal 'D', Sheet.column_index(3)
         | 
| 14 | 
            +
                assert_equal 'Y', Sheet.column_index(24)
         | 
| 15 | 
            +
                assert_equal 'Z', Sheet.column_index(25)
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              def test_column_index_two_digits
         | 
| 19 | 
            +
                assert_equal 'AA', Sheet.column_index(0+26)
         | 
| 20 | 
            +
                assert_equal 'AB', Sheet.column_index(1+26)
         | 
| 21 | 
            +
                assert_equal 'AC', Sheet.column_index(2+26)
         | 
| 22 | 
            +
                assert_equal 'AD', Sheet.column_index(3+26)
         | 
| 23 | 
            +
                assert_equal 'AZ', Sheet.column_index(25+26)
         | 
| 24 | 
            +
                assert_equal 'BA', Sheet.column_index(25+26+1)
         | 
| 25 | 
            +
                assert_equal 'BB', Sheet.column_index(25+26+2)
         | 
| 26 | 
            +
                assert_equal 'BC', Sheet.column_index(25+26+3)
         | 
| 27 | 
            +
              end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
              def test_format_field_for_strings
         | 
| 30 | 
            +
                v = Sheet.format_field_and_type_and_style "<escape this>"
         | 
| 31 | 
            +
                assert_equal [:inlineStr, "<is><t><escape this></t></is>", 5], v
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
              def test_format_field_for_numbers
         | 
| 35 | 
            +
                v = Sheet.format_field_and_type_and_style 3
         | 
| 36 | 
            +
                assert_equal [:n, "<v>3</v>", 3], v
         | 
| 37 | 
            +
                v = Sheet.format_field_and_type_and_style(BigDecimal.new("45"))
         | 
| 38 | 
            +
                assert_equal [:n, "<v>45.0</v>", 4], v
         | 
| 39 | 
            +
                v = Sheet.format_field_and_type_and_style(9.32)
         | 
| 40 | 
            +
                assert_equal [:n, "<v>9.32</v>", 4], v
         | 
| 41 | 
            +
              end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
              def test_format_field_for_date
         | 
| 44 | 
            +
                v = Sheet.format_field_and_type_and_style(Date.parse('2010-Jul-24'))
         | 
| 45 | 
            +
                assert_equal [:n, "<v>#{38921+1462}</v>", 2], v
         | 
| 46 | 
            +
              end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
              def test_format_field_for_datetime
         | 
| 49 | 
            +
                v = Sheet.format_field_and_type_and_style(Time.parse('2010-Jul-24 12:00 UTC'))
         | 
| 50 | 
            +
                assert_equal [:n, "<v>#{38921.5+1462}</v>", 1], v
         | 
| 51 | 
            +
              end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
             | 
| 54 | 
            +
              def test_format_field_for_boolean
         | 
| 55 | 
            +
                v = Sheet.format_field_and_type_and_style(false)
         | 
| 56 | 
            +
                assert_equal [:b, "<v>0</v>", 6], v
         | 
| 57 | 
            +
                v = Sheet.format_field_and_type_and_style(true)
         | 
| 58 | 
            +
                assert_equal [:b, "<v>1</v>", 6], v
         | 
| 59 | 
            +
              end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
              def test_add_row
         | 
| 62 | 
            +
                str = ""
         | 
| 63 | 
            +
                io = StringIO.new(str)
         | 
| 64 | 
            +
                Sheet.new(nil, 'name', io) do |sheet|
         | 
| 65 | 
            +
                  sheet.add_row ['this is ', 'a new row']
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
                doc = REXML::Document.new str
         | 
| 68 | 
            +
                assert_equal 'worksheet', doc.root.name
         | 
| 69 | 
            +
                sheetdata = doc.root.elements['sheetData']
         | 
| 70 | 
            +
                assert sheetdata
         | 
| 71 | 
            +
                row = sheetdata.elements['row']
         | 
| 72 | 
            +
                assert row
         | 
| 73 | 
            +
                assert_equal '1', row.attributes['r']
         | 
| 74 | 
            +
                assert_equal 2, row.elements.to_a.size
         | 
| 75 | 
            +
                assert_equal ["r", "s", "t"], row.elements.to_a[0].attributes.keys
         | 
| 76 | 
            +
              end
         | 
| 77 | 
            +
             | 
| 78 | 
            +
             | 
| 79 | 
            +
            end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
            end
         | 
| @@ -0,0 +1,29 @@ | |
| 1 | 
            +
            require File.dirname(__FILE__) + '/test_helper.rb'
         | 
| 2 | 
            +
            require 'fileutils'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            class SimpleXlsxTest < Test::Unit::TestCase
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              def test_top_level
         | 
| 7 | 
            +
                FileUtils.rm_f "test.xlsx"
         | 
| 8 | 
            +
                o = SimpleXlsx::Serializer.new("test.xlsx") do |doc|
         | 
| 9 | 
            +
                  doc.add_sheet "First" do |sheet|
         | 
| 10 | 
            +
                    sheet.add_row ["Hello", "World", 3.14, 7]
         | 
| 11 | 
            +
                    sheet.add_row ["Another", "Row", Date.today, Time.parse('2010-Jul-24 12:00 UTC')]
         | 
| 12 | 
            +
                  end
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              if false
         | 
| 17 | 
            +
                def test_top_level_stream
         | 
| 18 | 
            +
                  File.open "test_stream.xlsx", "wb" do |stream|
         | 
| 19 | 
            +
                    o = SimpleXlsx::Serializer.new(stream) do |doc|
         | 
| 20 | 
            +
                      doc.add_sheet "First" do |sheet|
         | 
| 21 | 
            +
                        sheet.add_row ["Hello", "World", 3.14]
         | 
| 22 | 
            +
                        sheet.add_row ["Another", "Row", Date.today]
         | 
| 23 | 
            +
                      end
         | 
| 24 | 
            +
                    end
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
              end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            end
         | 
    
        data/test/test_helper.rb
    ADDED
    
    
    
        metadata
    ADDED
    
    | @@ -0,0 +1,113 @@ | |
| 1 | 
            +
            --- !ruby/object:Gem::Specification 
         | 
| 2 | 
            +
            name: simple_xlsx_writer
         | 
| 3 | 
            +
            version: !ruby/object:Gem::Version 
         | 
| 4 | 
            +
              hash: 13
         | 
| 5 | 
            +
              prerelease: false
         | 
| 6 | 
            +
              segments: 
         | 
| 7 | 
            +
              - 0
         | 
| 8 | 
            +
              - 5
         | 
| 9 | 
            +
              - 3
         | 
| 10 | 
            +
              version: 0.5.3
         | 
| 11 | 
            +
            platform: ruby
         | 
| 12 | 
            +
            authors: 
         | 
| 13 | 
            +
            - Dee Zsombor
         | 
| 14 | 
            +
            autorequire: 
         | 
| 15 | 
            +
            bindir: bin
         | 
| 16 | 
            +
            cert_chain: []
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            date: 2010-08-20 00:00:00 +03:00
         | 
| 19 | 
            +
            default_executable: 
         | 
| 20 | 
            +
            dependencies: 
         | 
| 21 | 
            +
            - !ruby/object:Gem::Dependency 
         | 
| 22 | 
            +
              name: rubyzip
         | 
| 23 | 
            +
              prerelease: false
         | 
| 24 | 
            +
              requirement: &id001 !ruby/object:Gem::Requirement 
         | 
| 25 | 
            +
                none: false
         | 
| 26 | 
            +
                requirements: 
         | 
| 27 | 
            +
                - - ">="
         | 
| 28 | 
            +
                  - !ruby/object:Gem::Version 
         | 
| 29 | 
            +
                    hash: 51
         | 
| 30 | 
            +
                    segments: 
         | 
| 31 | 
            +
                    - 0
         | 
| 32 | 
            +
                    - 9
         | 
| 33 | 
            +
                    - 4
         | 
| 34 | 
            +
                    version: 0.9.4
         | 
| 35 | 
            +
              type: :runtime
         | 
| 36 | 
            +
              version_requirements: *id001
         | 
| 37 | 
            +
            - !ruby/object:Gem::Dependency 
         | 
| 38 | 
            +
              name: fast_xs
         | 
| 39 | 
            +
              prerelease: false
         | 
| 40 | 
            +
              requirement: &id002 !ruby/object:Gem::Requirement 
         | 
| 41 | 
            +
                none: false
         | 
| 42 | 
            +
                requirements: 
         | 
| 43 | 
            +
                - - ">="
         | 
| 44 | 
            +
                  - !ruby/object:Gem::Version 
         | 
| 45 | 
            +
                    hash: 5
         | 
| 46 | 
            +
                    segments: 
         | 
| 47 | 
            +
                    - 0
         | 
| 48 | 
            +
                    - 7
         | 
| 49 | 
            +
                    - 3
         | 
| 50 | 
            +
                    version: 0.7.3
         | 
| 51 | 
            +
              type: :runtime
         | 
| 52 | 
            +
              version_requirements: *id002
         | 
| 53 | 
            +
            description: 
         | 
| 54 | 
            +
            email: zsombor@primalgrasp.com
         | 
| 55 | 
            +
            executables: []
         | 
| 56 | 
            +
             | 
| 57 | 
            +
            extensions: []
         | 
| 58 | 
            +
             | 
| 59 | 
            +
            extra_rdoc_files: 
         | 
| 60 | 
            +
            - README
         | 
| 61 | 
            +
            files: 
         | 
| 62 | 
            +
            - lib/simple_xlsx.rb
         | 
| 63 | 
            +
            - lib/simple_xlsx/xml_escape.rb
         | 
| 64 | 
            +
            - lib/simple_xlsx/serializer.rb
         | 
| 65 | 
            +
            - lib/simple_xlsx/monkey_patches_for_true_zip_stream.rb
         | 
| 66 | 
            +
            - lib/simple_xlsx/document.rb
         | 
| 67 | 
            +
            - lib/simple_xlsx/sheet.rb
         | 
| 68 | 
            +
            - LICENSE
         | 
| 69 | 
            +
            - Rakefile
         | 
| 70 | 
            +
            - test/simple_xlsx_test.rb
         | 
| 71 | 
            +
            - test/simple_xlsx/document_test.rb
         | 
| 72 | 
            +
            - test/simple_xlsx/sheet_test.rb
         | 
| 73 | 
            +
            - test/test_helper.rb
         | 
| 74 | 
            +
            - README
         | 
| 75 | 
            +
            has_rdoc: true
         | 
| 76 | 
            +
            homepage: http://simplxlsxwriter.rubyforge.org
         | 
| 77 | 
            +
            licenses: []
         | 
| 78 | 
            +
             | 
| 79 | 
            +
            post_install_message: 
         | 
| 80 | 
            +
            rdoc_options: []
         | 
| 81 | 
            +
             | 
| 82 | 
            +
            require_paths: 
         | 
| 83 | 
            +
            - lib
         | 
| 84 | 
            +
            required_ruby_version: !ruby/object:Gem::Requirement 
         | 
| 85 | 
            +
              none: false
         | 
| 86 | 
            +
              requirements: 
         | 
| 87 | 
            +
              - - ">="
         | 
| 88 | 
            +
                - !ruby/object:Gem::Version 
         | 
| 89 | 
            +
                  hash: 3
         | 
| 90 | 
            +
                  segments: 
         | 
| 91 | 
            +
                  - 0
         | 
| 92 | 
            +
                  version: "0"
         | 
| 93 | 
            +
            required_rubygems_version: !ruby/object:Gem::Requirement 
         | 
| 94 | 
            +
              none: false
         | 
| 95 | 
            +
              requirements: 
         | 
| 96 | 
            +
              - - ">="
         | 
| 97 | 
            +
                - !ruby/object:Gem::Version 
         | 
| 98 | 
            +
                  hash: 3
         | 
| 99 | 
            +
                  segments: 
         | 
| 100 | 
            +
                  - 0
         | 
| 101 | 
            +
                  version: "0"
         | 
| 102 | 
            +
            requirements: []
         | 
| 103 | 
            +
             | 
| 104 | 
            +
            rubyforge_project: simple_xlsx_writer
         | 
| 105 | 
            +
            rubygems_version: 1.3.7
         | 
| 106 | 
            +
            signing_key: 
         | 
| 107 | 
            +
            specification_version: 3
         | 
| 108 | 
            +
            summary: Just as the name says, simple writter for Office 2007+ Excel files
         | 
| 109 | 
            +
            test_files: 
         | 
| 110 | 
            +
            - test/simple_xlsx_test.rb
         | 
| 111 | 
            +
            - test/simple_xlsx/document_test.rb
         | 
| 112 | 
            +
            - test/simple_xlsx/sheet_test.rb
         | 
| 113 | 
            +
            - test/test_helper.rb
         |