Class: Woa::Energon::OpenXmlHelper

Inherits:
Object
  • Object
show all
Defined in:
lib/energon/open_xml_helper.rb

Overview

This class is an interface with OpenXML files. It manages the content of the file so that caller classes just manage xml Object (ReXml). It’s not possible at this time to work with streams beacause of the zip library (rubyzip), it has to be done via files.

The support is not fully functional because of rubyzip which is buggy and generates wrong zip file not recognized by Office.

:include: rdoc-header

Constant Summary collapse

TypeWord =
0
TypeExcel =
TypeWord.next

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(template, type) ⇒ OpenXmlHelper

  • ftemplate: the name of the file

  • type: the type of the file (TypeWord or TypeExcel)



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/energon/open_xml_helper.rb', line 43

def initialize(template, type)
  raise InvalidOpenXmlDocument, "Wrong Type" unless type == TypeWord || type == TypeExcel
  @type = type
  @template = template
  
#      @zip_file = ZipFile.open(template)
############# tempdir ##############
  n = 0
  begin
    @tmpdir = File.join(File.dirname(@template), "tempdir.#{$$}.#{n}.dir")
    n = n.next
  end while File.exist?(@tmpdir)

  ObjectSpace.define_finalizer(self, OpenXmlHelper.finalize(@tmpdir))
  FileUtils.mkdir(@tmpdir)

  ZipFile.foreach(template) do |entry|
    next if entry.directory?
    file = "#{@tmpdir}/#{entry.name}"
    dir = File.dirname(file)
    FileUtils.mkdir_p(dir) unless File.exist?(dir)
    File.open(file, 'wb') do |file|
      entry.get_input_stream {|stream| file.write(stream.read) }
    end
  end
############# tempdir ##############
  
  rels = xml(read("_rels/.rels")) rescue nil
  raise InvalidOpenXmlDocument, "No _rels/.rels file" if rels.nil?
  
  elements = REXML::XPath.match(rels, "/Relationships/Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument']")

  raise InvalidOpenXmlDocument, "This version of OpenXML Helper can't handle OpenXml files with more than one main document" unless elements.size == 1
  
  target = elements.first.attribute('Target').to_s
  
  @documents = {}
  @shared_strings = nil
  @workbook = nil
  @worksheets = nil
  
  case type
    when TypeWord
      add_document(target) if target =~ /^word\/document.xml$/
    when TypeExcel
      if target =~ /^xl\/workbook.xml$/
        workbook = xml(read(target))
        add_document(target, workbook) 
        @workbook = workbook
      end
  end

  raise InvalidOpenXmlDocument if @documents.empty?

  case type
    when TypeWord
      add_word_documents
    when TypeExcel
      add_excel_documents
  end
end

Instance Attribute Details

#shared_stringsObject (readonly)

Returns the value of attribute shared_strings.



27
28
29
# File 'lib/energon/open_xml_helper.rb', line 27

def shared_strings
  @shared_strings
end

#typeObject (readonly)

Returns the value of attribute type.



27
28
29
# File 'lib/energon/open_xml_helper.rb', line 27

def type
  @type
end

#workbookObject (readonly)

Returns the value of attribute workbook.



28
29
30
# File 'lib/energon/open_xml_helper.rb', line 28

def workbook
  @workbook
end

#worksheetsObject (readonly)

Returns the value of attribute worksheets.



29
30
31
# File 'lib/energon/open_xml_helper.rb', line 29

def worksheets
  @worksheets
end

Class Method Details

.finalize(tmpdir) ⇒ Object

tempdir ##############



33
34
35
36
37
# File 'lib/energon/open_xml_helper.rb', line 33

def OpenXmlHelper.finalize(tmpdir)
  lambda do 
    FileUtils.remove_dir(tmpdir, true) if File.exist?(tmpdir)
  end
end

.new_excel(template) ⇒ Object

create directly a new Excel file

  • template: the name of the file



107
108
109
# File 'lib/energon/open_xml_helper.rb', line 107

def OpenXmlHelper.new_excel(template)
  OpenXmlHelper.new(template, TypeExcel)
end

.new_word(template) ⇒ Object

create directly a new Word file

  • template: the name of the file



113
114
115
# File 'lib/energon/open_xml_helper.rb', line 113

def OpenXmlHelper.new_word(template)
  OpenXmlHelper.new(template, TypeWord)
end

Instance Method Details

#documentsObject

it returns all the files which could contain some data (Text, Numbers, Dates, …). All the files who deal with the format, the style, … are not included

Each member of the Array is a REXML::Document



121
122
123
# File 'lib/energon/open_xml_helper.rb', line 121

def documents
  @documents.keys
end

#save(xml) ⇒ Object

Save the modified content of the file represented by a REXML::Document



126
127
128
# File 'lib/energon/open_xml_helper.rb', line 126

def save(xml)
  save_xml(xml, @documents[xml]) if @documents.include?(xml)
end

#writeObject Also known as: close

Write the final document (the zipfile) and close the file



131
132
133
134
135
136
137
138
139
140
# File 'lib/energon/open_xml_helper.rb', line 131

def write
  save_shared_strings
#      @zip_file.close
############# tempdir ##############
  FileUtils.rm(@template) if File.exist?(@template)
  FileUtils.cd(@tmpdir) do |dir|
    system("zip -q -r ../#{File.basename(@template)} .")
  end
############# tempdir ##############
end