odf-report 0.3.3 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,11 +3,20 @@ h1. ODF-REPORT
3
3
  Gem for generating .odt files by making strings, images, tables and sections replacements in a previously created .odt file.
4
4
 
5
5
 
6
+ h2. NEW!
7
+
8
+ <pre>
9
+ ODF-REPORT have been internally refactored. It now uses Nokogiri for parsing the documents, instead of Regex.
10
+
11
+ This provides for a much greater flexibility. As a result, I was able to implement nested sections.
12
+
13
+ Now sections can be nested inside sections, with fields, tables and others sections.
14
+ </pre>
15
+
6
16
  h2. INSTALL
7
17
 
8
18
  (sudo) gem install odf-report
9
19
 
10
-
11
20
  h2. USAGE
12
21
 
13
22
  h3. Step 1 -- the template
@@ -96,11 +105,11 @@ end
96
105
  </pre>
97
106
 
98
107
 
99
- h3. Sections (NEW!)
108
+ h3. Sections
100
109
 
101
110
  Sometimes, you have to repeat a whole chunk of a document, in a structure a lot more complex than a table. Now you can make a Section in your template and use it in this situations. Creating a Session in OpenOffice is as easy as select menu *Insert* and then *Section...*, and then choose a name for it.
102
111
 
103
- *Section* 's are lot like Tables, in the sense that you can pass a collection and have that section repeated for each member of the collection. *But*, Sections can have anything inside it, even Tables, as long as you pass the appropriate data structure.
112
+ *Section* 's are lot like Tables, in the sense that you can pass a collection and have that section repeated for each member of the collection. *But*, Sections can have anything inside it, even Tables *and nested Sections*, as long as you pass the appropriate data structure.
104
113
 
105
114
  Let's see an example:
106
115
 
@@ -133,6 +142,14 @@ Let's see an example:
133
142
  end
134
143
  end
135
144
 
145
+ s.add_section("SUB_NOTES", :notes) do |s1|
146
+
147
+ s1.add_field(:note_title) { |n| n.title }
148
+
149
+ s1.add_table ...
150
+
151
+ end
152
+
136
153
  end
137
154
 
138
155
  end
@@ -208,6 +225,7 @@ report.generate("./documents/")
208
225
  h3. REQUIREMENTS
209
226
 
210
227
  *rubyzip*: for manipulating the contents of the odt file, since it's actually a zip file.
228
+ *nokogiri*: for parsing and manipulating the document xml files.
211
229
 
212
230
 
213
231
  <hr/>
@@ -1,8 +1,12 @@
1
1
  require 'rubygems'
2
2
  require 'zip/zipfilesystem'
3
3
  require 'fileutils'
4
- require File.expand_path('../odf-report/file_ops',__FILE__)
5
- require File.expand_path('../odf-report/hash_gsub',__FILE__)
6
- require File.expand_path('../odf-report/section',__FILE__)
7
- require File.expand_path('../odf-report/table',__FILE__)
8
- require File.expand_path('../odf-report/report',__FILE__)
4
+ require 'nokogiri'
5
+
6
+ require File.expand_path('../odf-report/images', __FILE__)
7
+ require File.expand_path('../odf-report/file_ops', __FILE__)
8
+ require File.expand_path('../odf-report/hash_gsub', __FILE__)
9
+ require File.expand_path('../odf-report/nested', __FILE__)
10
+ require File.expand_path('../odf-report/section', __FILE__)
11
+ require File.expand_path('../odf-report/table', __FILE__)
12
+ require File.expand_path('../odf-report/report', __FILE__)
@@ -2,6 +2,19 @@ module ODFReport
2
2
 
3
3
  module FileOps
4
4
 
5
+ def create_new_file(dest)
6
+
7
+ if dest
8
+ FileUtils.cp(@template, dest)
9
+ new_file = dest
10
+ else
11
+ FileUtils.cp(@template, @tmp_dir)
12
+ new_file = "#{@tmp_dir}/#{File.basename(@template)}"
13
+ end
14
+
15
+ return new_file
16
+ end
17
+
5
18
  def random_filename(opts={})
6
19
  opts = {:chars => ('0'..'9').to_a + ('A'..'F').to_a + ('a'..'f').to_a,
7
20
  :length => 24, :prefix => '', :suffix => '',
@@ -22,6 +22,12 @@ module ODFReport
22
22
  s.to_s.gsub("\n", "<text:line-break/>")
23
23
  end
24
24
 
25
+ def node_hash_gsub!(_node, hash_of_values)
26
+ txt = _node.inner_html
27
+ hash_gsub!(txt, hash_of_values)
28
+ _node.inner_html = txt
29
+ end
30
+
25
31
  end
26
32
 
27
33
  end
@@ -0,0 +1,37 @@
1
+ module ODFReport
2
+
3
+ module Images
4
+
5
+ def find_image_name_matches(content)
6
+
7
+ @images.each_pair do |image_name, path|
8
+ #Search for the image placeholder path
9
+ image_rgx = Regexp.new("draw:name=\"#{image_name}\".*?>.*<draw:image.*?xlink:href=\"([^\s]*)\" .*?\/>.*</draw:frame>", Regexp::MULTILINE)
10
+ content_match = content.match(image_rgx)
11
+
12
+ if content_match
13
+ placeholder_path = content_match[1]
14
+ @image_names_replacements[path] = File.basename(placeholder_path)
15
+ end
16
+ end
17
+
18
+ end
19
+
20
+ def replace_images(new_file)
21
+
22
+ unless @images.empty?
23
+ image_dir_name = "Pictures"
24
+ FileUtils.mkdir(File.join("#{@tmp_dir}", image_dir_name))
25
+ @image_names_replacements.each_pair do |path, template_image|
26
+ template_image_path = File.join(image_dir_name, template_image)
27
+ update_file_from_zip(new_file, template_image_path) do |content|
28
+ content.replace File.read(path)
29
+ end
30
+ end
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+
37
+ end
@@ -0,0 +1,42 @@
1
+ module ODFReport
2
+
3
+ module Nested
4
+
5
+ def replace_values!(new_section, data_item)
6
+ node_hash_gsub!(new_section, get_fields_with_values(data_item))
7
+ end
8
+
9
+ def get_fields_with_values(data_item)
10
+
11
+ fields_with_values = {}
12
+ @fields.each do |field_name, block1|
13
+ fields_with_values[field_name] = block1.call(data_item) || ''
14
+ end
15
+
16
+ fields_with_values
17
+ end
18
+
19
+ def get_collection_from_item(item, collection_field)
20
+
21
+ if collection_field.is_a?(Array)
22
+ tmp = item.dup
23
+ collection_field.each do |f|
24
+ if f.is_a?(Hash)
25
+ tmp = tmp.send(f.keys[0], f.values[0])
26
+ else
27
+ tmp = tmp.send(f)
28
+ end
29
+ end
30
+ collection = tmp
31
+ elsif collection_field.is_a?(Hash)
32
+ collection = item.send(collection_field.keys[0], collection_field.values[0])
33
+ else
34
+ collection = item.send(collection_field)
35
+ end
36
+
37
+ return collection
38
+ end
39
+
40
+ end
41
+
42
+ end
@@ -1,7 +1,7 @@
1
1
  module ODFReport
2
2
 
3
3
  class Report
4
- include HashGsub, FileOps
4
+ include HashGsub, FileOps, Images
5
5
 
6
6
  attr_accessor :values, :tables, :images, :sections
7
7
 
@@ -14,35 +14,31 @@ class Report
14
14
  @image_names_replacements = {}
15
15
  @sections = []
16
16
 
17
- @tmp_dir = Dir.tmpdir + "/" + random_filename(:prefix=>'odt_')
17
+ @tmp_dir = File.join(Dir.tmpdir, random_filename(:prefix=>'odt_'))
18
18
  Dir.mkdir(@tmp_dir) unless File.exists? @tmp_dir
19
19
 
20
20
  yield(self)
21
21
 
22
22
  end
23
23
 
24
- def add_section(section_name, collection, &block)
25
- sec = Section.new(section_name)
26
- @sections << sec
27
-
28
- yield(sec)
29
-
30
- sec.populate(collection)
31
-
32
- end
33
-
34
- def add_field(field_tag, value)
35
- @values[field_tag] = value || ''
24
+ def add_field(field_tag, value='')
25
+ @values[field_tag] = value
36
26
  end
37
27
 
38
28
  def add_table(table_name, collection, opts={}, &block)
39
- opts[:name] = table_name
29
+ opts.merge!(:name => table_name, :collection => collection)
40
30
  tab = Table.new(opts)
41
- yield(tab)
42
31
  @tables << tab
43
32
 
44
- tab.populate(collection)
33
+ yield(tab)
34
+ end
35
+
36
+ def add_section(section_name, collection, opts={}, &block)
37
+ opts.merge!(:name => section_name, :collection => collection)
38
+ sec = Section.new(opts)
39
+ @sections << sec
45
40
 
41
+ yield(sec)
46
42
  end
47
43
 
48
44
  def add_image(name, path)
@@ -51,41 +47,27 @@ class Report
51
47
 
52
48
  def generate(dest = nil)
53
49
 
54
- if dest
50
+ new_file = create_new_file(dest)
55
51
 
56
- FileUtils.cp(@template, dest)
57
- new_file = dest
52
+ %w(content.xml styles.xml).each do |content_file|
58
53
 
59
- else
54
+ update_file_from_zip(new_file, content_file) do |txt|
60
55
 
61
- FileUtils.cp(@template, @tmp_dir)
62
- new_file = "#{@tmp_dir}/#{File.basename(@template)}"
56
+ parse_document(txt) do |doc|
63
57
 
64
- end
58
+ replace_fields!(doc)
59
+ replace_sections!(doc)
60
+ replace_tables!(doc)
65
61
 
66
- %w(content.xml styles.xml).each do |content_file|
67
-
68
- update_file_from_zip(new_file, content_file) do |txt|
62
+ end
69
63
 
70
- replace_fields!(txt)
71
- replace_tables!(txt)
64
+ #TO_DO: make image use Nokogiri
72
65
  find_image_name_matches(txt)
73
- replace_sections!(txt)
74
-
75
66
  end
76
67
 
77
68
  end
78
69
 
79
- unless @images.empty?
80
- image_dir_name = "Pictures"
81
- FileUtils.mkdir(File.join("#{@tmp_dir}", image_dir_name))
82
- @image_names_replacements.each_pair do |path, template_image|
83
- template_image_path = File.join(image_dir_name, template_image)
84
- update_file_from_zip(new_file, template_image_path) do |content|
85
- content.replace File.read(path)
86
- end
87
- end
88
- end
70
+ replace_images(new_file)
89
71
 
90
72
  new_file
91
73
 
@@ -93,37 +75,28 @@ class Report
93
75
 
94
76
  private
95
77
 
78
+ def parse_document(txt)
79
+ doc = Nokogiri::XML(txt)
80
+ yield doc
81
+ txt.replace(doc.to_s)
82
+ end
83
+
96
84
  def replace_fields!(content)
97
- hash_gsub!(content, @values)
85
+ node_hash_gsub!(content, @values)
98
86
  end
99
87
 
100
88
  def replace_tables!(content)
101
-
102
89
  @tables.each do |table|
103
90
  table.replace!(content)
104
91
  end
105
-
106
92
  end
107
93
 
108
94
  def replace_sections!(content)
109
-
110
95
  @sections.each do |section|
111
96
  section.replace!(content)
112
97
  end
113
-
114
98
  end
115
99
 
116
- def find_image_name_matches(content)
117
- @images.each_pair do |image_name, path|
118
- #Search for the image placeholder path
119
- image_rgx = Regexp.new("draw:name=\"#{image_name}\".*?><draw:image.*?xlink:href=\"([^\s]*)\" .*?/></draw:frame>")
120
- content_match = content.match(image_rgx)
121
- if content_match
122
- placeholder_path = content_match[1]
123
- @image_names_replacements[path] = File.basename(placeholder_path)
124
- end
125
- end
126
- end
127
100
  end
128
101
 
129
102
  end
@@ -1,113 +1,93 @@
1
1
  module ODFReport
2
2
 
3
- class Section
4
- include HashGsub
3
+ class Section
4
+ include HashGsub, Nested
5
5
 
6
- attr_accessor :fields, :tables, :data, :name
6
+ attr_accessor :fields, :tables, :data, :name, :collection_field, :parent
7
7
 
8
- def initialize(name)
9
- @name = name
8
+ def initialize(opts)
9
+ @name = opts[:name]
10
+ @collection_field = opts[:collection_field]
11
+ @collection = opts[:collection]
12
+ @parent = opts[:parent]
10
13
 
11
- @fields = {}
12
- @data = []
13
- @tables = []
14
- end
14
+ @fields = {}
15
15
 
16
- def add_field(name, field=nil, &block)
17
- if field
18
- @fields[name] = lambda { |item| item.send(field)}
19
- else
20
- @fields[name] = block
16
+ @tables = []
17
+ @sections = []
21
18
  end
22
- end
23
-
24
- def add_table(table_name, collection_field, opts={}, &block)
25
- opts.merge!(:name => table_name, :collection_field => collection_field)
26
- tab = Table.new(opts)
27
- yield(tab)
28
- @tables << tab
29
-
30
- end
31
19
 
32
- def populate(collection)
33
-
34
- collection.each do |item|
35
- row = {}
36
- @fields.each do |field_name, block1|
37
- row[field_name] = block1.call(item)
20
+ def add_field(name, field=nil, &block)
21
+ if field
22
+ @fields[name] = lambda { |item| item.send(field)}
23
+ elsif block_given?
24
+ @fields[name] = block
25
+ else
26
+ @fields[name] = lambda { |item| item.send(name)}
38
27
  end
28
+ end
39
29
 
40
- row[:tables] = {}
41
- @tables.each do |table|
42
- collection = get_collection_from_item(item, table.collection_field)
43
- row[:tables][table.name] = table.values(collection)
44
- end
30
+ def add_table(table_name, collection_field, opts={}, &block)
31
+ opts.merge!(:name => table_name, :collection_field => collection_field, :parent => self)
32
+ tab = Table.new(opts)
33
+ @tables << tab
45
34
 
46
- @data << row
35
+ yield(tab)
47
36
  end
48
37
 
49
- end
38
+ def add_section(section_name, collection_field, opts={}, &block)
39
+ opts.merge!(:name => section_name, :collection_field => collection_field, :parent => self)
40
+ sec = Section.new(opts)
41
+ @sections << sec
50
42
 
51
- def replace!(content)
43
+ yield(sec)
44
+ end
52
45
 
53
- # search for the table inside the content
54
- section_rgx = Regexp.new("(<text:section.*?text:name=\"#{@name}.*?>(.*?)<\/text:section>)", "m")
55
- section_match = content.match(section_rgx)
46
+ def populate!(row)
47
+ @collection = get_collection_from_item(row, @collection_field) if row
48
+ end
56
49
 
57
- if section_match
58
- section_full = section_match[0]
59
- section_content = section_match[2]
50
+ def replace!(doc, row = nil)
60
51
 
61
- # extract the section from the content
62
- content.gsub!(section_full, "[SECTION_#{@name}]")
52
+ return unless section = find_section_node(doc)
63
53
 
64
- new_content = ""
54
+ template = section.dup
65
55
 
66
- # for each record
67
- @data.each do |_values|
56
+ populate!(row)
68
57
 
69
- # generates one new row (table-row), based in the model extracted
70
- # from the original table
71
- tmp_row = section_content.dup
58
+ @collection.each do |data_item|
59
+ new_section = template.dup
72
60
 
73
- # replace values in the section_content and stores in new_content
74
- hash_gsub!(tmp_row, _values)
61
+ replace_values!(new_section, data_item)
75
62
 
76
63
  @tables.each do |t|
77
- t.replace!(tmp_row, _values[:tables][t.name])
64
+ t.replace!(new_section, data_item)
65
+ end
66
+
67
+ @sections.each do |s|
68
+ s.replace!(new_section, data_item)
78
69
  end
79
70
 
80
- new_content << tmp_row
71
+ section.before(new_section)
72
+
81
73
  end
82
74
 
83
- # replace back the table into content
84
- content.gsub!("[SECTION_#{@name}]", new_content)
75
+ section.remove
85
76
 
86
- end # if table match
77
+ end # replace_section
87
78
 
88
- end # replace_section
79
+ private
89
80
 
90
- private
81
+ def find_section_node(doc)
91
82
 
92
- def get_collection_from_item(item, collection_field)
83
+ prefix = @parent ? "" : "//"
84
+
85
+ sections = doc.xpath("#{prefix}text:section[@text:name='#{@name}']")
86
+
87
+ sections.empty? ? nil : sections.first
93
88
 
94
- if collection_field.is_a?(Array)
95
- tmp = item.dup
96
- collection_field.each do |f|
97
- if f.is_a?(Hash)
98
- tmp = tmp.send(f.keys[0], f.values[0])
99
- else
100
- tmp = tmp.send(f)
101
- end
102
- end
103
- collection = tmp
104
- else
105
- collection = item.send(collection_field)
106
89
  end
107
90
 
108
- return collection
109
91
  end
110
92
 
111
- end
112
-
113
93
  end
@@ -1,19 +1,20 @@
1
1
  module ODFReport
2
2
 
3
3
  class Table
4
- include HashGsub
4
+ include HashGsub, Nested
5
5
 
6
- attr_accessor :fields, :rows, :name, :collection_field, :data, :header
6
+ attr_accessor :fields, :rows, :name, :collection_field, :data, :header, :parent
7
7
 
8
8
  def initialize(opts)
9
9
  @name = opts[:name]
10
10
  @collection_field = opts[:collection_field]
11
11
  @collection = opts[:collection]
12
- @header = opts[:header] || false
12
+ @parent = opts[:parent]
13
13
 
14
14
  @fields = {}
15
- @rows = []
16
- @data = []
15
+
16
+ @template_rows = []
17
+ @header = opts[:header] || false
17
18
  end
18
19
 
19
20
  def add_column(name, field=nil, &block)
@@ -26,104 +27,68 @@ class Table
26
27
  end
27
28
  end
28
29
 
29
- def values(collection)
30
- ret = []
31
- collection.each do |item|
32
- row = {}
33
- @fields.each do |field_name, block1|
34
- row[field_name] = block1.call(item) || ''
35
- end
36
- ret << row
37
- end
38
- ret
39
- end
40
-
41
- def populate(collection)
42
- @data = values(collection)
30
+ def populate!(row)
31
+ @collection = get_collection_from_item(row, @collection_field) if row
43
32
  end
44
33
 
45
- def replace!(content, rows = nil)
46
- @data = rows if rows
47
-
48
- # search for the table inside the content
49
- table_rgx = Regexp.new("(<table:table table:name=\"#{@name}.*?>.*?<\/table:table>)", "m")
50
- table_match = content.match(table_rgx)
51
-
52
- if table_match
53
- table = table_match[0]
34
+ def replace!(doc, row = nil)
54
35
 
55
- # extract the table from the content
56
- content.gsub!(table, "[TABLE_#{@name}]")
36
+ return unless table = find_table_node(doc)
57
37
 
58
- # search for the table:row's
59
- row_rgx = Regexp.new("(<table:table-row.*?<\/table:table-row>)", "m")
38
+ populate!(row)
60
39
 
61
- # use scan (instead of match) as the table can have more than one table-row (header and data)
62
- # and scan returns all matches
63
- row_match = table.scan(row_rgx)
40
+ @template_rows = table.xpath("table:table-row")
64
41
 
65
- unless row_match.empty?
42
+ @collection.each do |data_item|
66
43
 
67
- replace_rows!(table, row_match)
44
+ new_node = get_next_row
68
45
 
69
- new_rows = ""
46
+ replace_values!(new_node, data_item)
70
47
 
71
- # for each record
72
- @data.each do |_values|
48
+ table.add_child(new_node)
73
49
 
74
- # generates one new row (table-row), based in the model extracted
75
- # from the original table
76
- tmp_row = get_next_row.dup
77
-
78
- # replace values in the model_row and stores in new_rows
79
- hash_gsub!(tmp_row, _values)
80
-
81
- new_rows << tmp_row
82
- end
50
+ end
83
51
 
84
- # replace back the lines into the table
85
- table.gsub!("[ROW_#{@name}]", new_rows)
52
+ @template_rows.each_with_index do |r, i|
53
+ r.remove if (get_start_node..template_lenght) === i
54
+ end
86
55
 
87
- end # unless row_match.empty?
56
+ end # replace
88
57
 
89
- # replace back the table into content
90
- if @data.empty?
91
- content.gsub!("[TABLE_#{@name}]", "")
92
- else
93
- content.gsub!("[TABLE_#{@name}]", table)
94
- end
58
+ private
95
59
 
96
- end # if table match
60
+ def get_next_row
61
+ @row_cursor = get_start_node unless defined?(@row_cursor)
97
62
 
98
- end # replace
63
+ ret = @template_rows[@row_cursor]
64
+ if @template_rows.size == @row_cursor + 1
65
+ @row_cursor = get_start_node
66
+ else
67
+ @row_cursor += 1
68
+ end
69
+ return ret.dup
70
+ end
99
71
 
100
- private
72
+ def get_start_node
73
+ @header ? 1 : 0
74
+ end
101
75
 
102
- def replace_rows!(table, rows)
76
+ def reset
77
+ @row_cursor = get_start_node
78
+ end
103
79
 
104
- rows.delete_at(0) if @header # ignore the header
80
+ def template_lenght
81
+ @tl ||= @template_rows.size
82
+ end
105
83
 
106
- @rows = rows.dup
107
- @row_cursor = 0
84
+ def find_table_node(doc)
108
85
 
109
- # extract the rows from the table
110
- first = rows.delete_at(0)[0]
111
- table.gsub!(first, "[ROW_#{@name}]")
86
+ prefix = @parent ? "" : "//"
112
87
 
113
- rows.each do |r|
114
- table.gsub!(r[0], "")
115
- end
88
+ tables = doc.xpath("#{prefix}table:table[@table:name='#{@name}']")
116
89
 
117
- end
90
+ tables.empty? ? nil : tables.first
118
91
 
119
- def get_next_row
120
- ret = @rows[@row_cursor]
121
- if @rows.size == @row_cursor + 1
122
- @row_cursor = 0
123
- else
124
- @row_cursor += 1
125
- end
126
- return ret[0]
127
92
  end
128
93
 
129
94
  end
@@ -2,15 +2,15 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{odf-report}
5
- s.version = "0.3.3"
5
+ s.version = "0.4.0"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Sandro Duarte"]
9
- s.date = %q{2011-01-24}
9
+ s.date = %q{2011-09-23}
10
10
  s.description = %q{Generates ODF files, given a template (.odt) and data, replacing tags}
11
11
  s.email = %q{sandrods@gmail.com}
12
12
  s.extra_rdoc_files = ["lib/odf-report.rb", "README.textile"]
13
- s.files = %w{lib/odf-report.rb odf-report.gemspec README.textile test/test.odt test/test.rb Manifest lib/odf-report/report.rb lib/odf-report/table.rb lib/odf-report/section.rb lib/odf-report/file_ops.rb lib/odf-report/hash_gsub.rb }
13
+ s.files = %w{lib/odf-report.rb odf-report.gemspec README.textile Manifest lib/odf-report/report.rb lib/odf-report/table.rb lib/odf-report/section.rb lib/odf-report/file_ops.rb lib/odf-report/hash_gsub.rb lib/odf-report/images.rb lib/odf-report/nested.rb }
14
14
  s.has_rdoc = false
15
15
  s.homepage = %q{}
16
16
  s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Odf-report", "--main", "README.textile"]
@@ -24,10 +24,13 @@ Gem::Specification.new do |s|
24
24
 
25
25
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
26
26
  s.add_runtime_dependency(%q<rubyzip>, [">= 0", ">= 0.9.4"])
27
+ s.add_runtime_dependency(%q<nokogiri>, [">= 0", ">= 1.5.0"])
27
28
  else
28
29
  s.add_dependency(%q<rubyzip>, [">= 0", ">= 0.9.4"])
30
+ s.add_dependency(%q<nokogiri>, [">= 0", ">= 1.5.0"])
29
31
  end
30
32
  else
31
33
  s.add_dependency(%q<rubyzip>, [">= 0", ">= 0.9.4"])
34
+ s.add_dependency(%q<nokogiri>, [">= 0", ">= 1.5.0"])
32
35
  end
33
36
  end
metadata CHANGED
@@ -1,97 +1,91 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: odf-report
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 3
8
- - 3
9
- version: 0.3.3
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.0
5
+ prerelease:
10
6
  platform: ruby
11
- authors:
7
+ authors:
12
8
  - Sandro Duarte
13
9
  autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
-
17
- date: 2011-01-24 00:00:00 -02:00
18
- default_executable:
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
12
+ date: 2011-09-23 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
21
15
  name: rubyzip
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
24
- requirements:
25
- - - ">="
26
- - !ruby/object:Gem::Version
27
- segments:
28
- - 0
29
- version: "0"
30
- - - ">="
31
- - !ruby/object:Gem::Version
32
- segments:
33
- - 0
34
- - 9
35
- - 4
16
+ requirement: &2152736240 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ - - ! '>='
23
+ - !ruby/object:Gem::Version
36
24
  version: 0.9.4
37
25
  type: :runtime
38
- version_requirements: *id001
26
+ prerelease: false
27
+ version_requirements: *2152736240
28
+ - !ruby/object:Gem::Dependency
29
+ name: nokogiri
30
+ requirement: &2152735160 !ruby/object:Gem::Requirement
31
+ none: false
32
+ requirements:
33
+ - - ! '>='
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ - - ! '>='
37
+ - !ruby/object:Gem::Version
38
+ version: 1.5.0
39
+ type: :runtime
40
+ prerelease: false
41
+ version_requirements: *2152735160
39
42
  description: Generates ODF files, given a template (.odt) and data, replacing tags
40
43
  email: sandrods@gmail.com
41
44
  executables: []
42
-
43
45
  extensions: []
44
-
45
- extra_rdoc_files:
46
+ extra_rdoc_files:
46
47
  - lib/odf-report.rb
47
48
  - README.textile
48
- files:
49
+ files:
49
50
  - lib/odf-report.rb
50
51
  - odf-report.gemspec
51
52
  - README.textile
52
- - test/test.odt
53
- - test/test.rb
54
53
  - Manifest
55
54
  - lib/odf-report/report.rb
56
55
  - lib/odf-report/table.rb
57
56
  - lib/odf-report/section.rb
58
57
  - lib/odf-report/file_ops.rb
59
58
  - lib/odf-report/hash_gsub.rb
60
- has_rdoc: true
61
- homepage: ""
59
+ - lib/odf-report/images.rb
60
+ - lib/odf-report/nested.rb
61
+ homepage: ''
62
62
  licenses: []
63
-
64
63
  post_install_message:
65
- rdoc_options:
64
+ rdoc_options:
66
65
  - --line-numbers
67
66
  - --inline-source
68
67
  - --title
69
68
  - Odf-report
70
69
  - --main
71
70
  - README.textile
72
- require_paths:
71
+ require_paths:
73
72
  - lib
74
- required_ruby_version: !ruby/object:Gem::Requirement
75
- requirements:
76
- - - ">="
77
- - !ruby/object:Gem::Version
78
- segments:
79
- - 0
80
- version: "0"
81
- required_rubygems_version: !ruby/object:Gem::Requirement
82
- requirements:
83
- - - ">="
84
- - !ruby/object:Gem::Version
85
- segments:
86
- - 1
87
- - 2
88
- version: "1.2"
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ none: false
81
+ requirements:
82
+ - - ! '>='
83
+ - !ruby/object:Gem::Version
84
+ version: '1.2'
89
85
  requirements: []
90
-
91
86
  rubyforge_project:
92
- rubygems_version: 1.3.6
87
+ rubygems_version: 1.8.10
93
88
  signing_key:
94
89
  specification_version: 2
95
90
  summary: Generates ODF files, given a template (.odt) and data, replacing tags
96
91
  test_files: []
97
-
Binary file
@@ -1,78 +0,0 @@
1
- require '../lib/odf-report'
2
- require 'ostruct'
3
-
4
- col1 = []
5
- (1..15).each do |i|
6
- col1 << OpenStruct.new({:name=>"name #{i}", :id=>i, :address=>"this is address #{i}"})
7
- end
8
-
9
-
10
- col2 = []
11
- col2 << OpenStruct.new({:name=>"josh harnet", :id=>"02", :address=>"testing <&> ", :phone=>99025668, :zip=>"90420-002"})
12
- col2 << OpenStruct.new({:name=>"sandro duarte", :id=>"45", :address=>"address with &", :phone=>88774451, :zip=>"90490-002"})
13
- col2 << OpenStruct.new({:name=>"ellen bicca", :id=>"77", :address=>"<address with escaped html>", :phone=>77025668, :zip=>"94420-002"})
14
- col2 << OpenStruct.new({:name=>"luiz garcia", :id=>"88", :address=>"address with\nlinebreak", :phone=>27025668, :zip=>"94520-025"})
15
-
16
- report = ODFReport::Report.new("test.odt") do |r|
17
-
18
- r.add_field("HEADER_FIELD", "This field was in the HEADER")
19
-
20
- r.add_field("TAG_01", "New tag")
21
- r.add_field("TAG_02", "TAG-2 -> New tag")
22
-
23
- r.add_table("TABLE_01", col1, :header=>true) do |t|
24
- t.add_column(:field_01, :id)
25
- t.add_column(:field_02, :name)
26
- t.add_column(:field_03, :address)
27
- end
28
-
29
- r.add_table("TABLE_02", col2) do |t|
30
- t.add_column(:field_04, :id)
31
- t.add_column(:field_05, :name)
32
- t.add_column(:field_06, :address)
33
- t.add_column(:field_07, :phone)
34
- t.add_column(:field_08, :zip)
35
- end
36
-
37
- r.add_image("graphics1", File.join(Dir.pwd, 'piriapolis.jpg'))
38
-
39
- end
40
-
41
- report.generate("result.odt")
42
-
43
- class Item
44
- attr_accessor :name, :sid, :children
45
- def initialize(_name, _sid, _children=[])
46
- @name=_name
47
- @sid=_sid
48
- @children=_children
49
- end
50
- end
51
-
52
- items = []
53
- items << Item.new("Dexter Morgan", '007', %w(sawyer juliet hurley locke jack freckles))
54
- items << Item.new("Danny Crane", '302', %w(sidney sloane jack michael marshal))
55
- items << Item.new("Coach Taylor", '220', %w(meredith christina izzie alex george))
56
-
57
- report = ODFReport::Report.new("sections.odt") do |r|
58
-
59
- r.add_field("TAG_01", "New tag")
60
- r.add_field("TAG_02", "TAG-2 -> New tag")
61
-
62
- r.add_section("SECTION_01", items) do |s|
63
-
64
- s.add_field('NAME') do |i|
65
- i.name
66
- end
67
-
68
- s.add_field('SID', :sid)
69
-
70
- s.add_table('TABLE_S1', :children, :header=>true) do |t|
71
- t.add_column('NAME1') { |item| "-> #{item}" }
72
- t.add_column('INV') { |item| item.to_s.reverse.upcase }
73
- end
74
- end
75
-
76
- end
77
-
78
- report.generate("section_result.odt")