reportbuilder 1.1.1 → 1.2.0
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/History.txt +7 -0
- data/Manifest.txt +7 -7
- data/Rakefile +9 -2
- data/lib/reportbuilder.rb +27 -17
- data/lib/reportbuilder/{generator.rb → builder.rb} +29 -16
- data/lib/reportbuilder/{generator → builder}/html.rb +7 -3
- data/lib/reportbuilder/{generator → builder}/rtf.rb +10 -6
- data/lib/reportbuilder/{generator → builder}/text.rb +7 -3
- data/lib/reportbuilder/image.rb +8 -8
- data/lib/reportbuilder/section.rb +3 -3
- data/lib/reportbuilder/table.rb +20 -12
- data/lib/reportbuilder/table/{htmlgenerator.rb → htmlbuilder.rb} +15 -11
- data/lib/reportbuilder/table/{rtfgenerator.rb → rtfbuilder.rb} +19 -15
- data/lib/reportbuilder/table/textbuilder.rb +52 -0
- data/test/test_image.rb +1 -1
- data/test/test_reportbuilder.rb +25 -2
- data/test/test_table.rb +61 -60
- metadata +73 -34
- data/lib/reportbuilder/table/textgenerator.rb +0 -55
data/History.txt
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
=== 1.2.0 / 2010-03-28
|
2
|
+
*ReporBuilder::Table
|
3
|
+
* Colspans works as expected on Html and Text. On Rtf the cells doesn't merge, because ruby-rtf doesn't support it.
|
4
|
+
* Better tests for Html and Text.
|
5
|
+
* Classes related to Generator renamed to Builder, because these correspond to Builder pattern
|
6
|
+
* Flexible codes for formats. You could use :text or :txt as :format for ReportBuilder#generate. See ReportBuilder::Builder.code for more information
|
7
|
+
|
1
8
|
=== 1.1.1 / 2010-03-24
|
2
9
|
* Test suite replaces Test::Unit for Test::MiniUnit and Hpricot for Nokogiri
|
3
10
|
* Bug fix: rtf generator doesn't accept a ReportBuilder::Image object
|
data/Manifest.txt
CHANGED
@@ -12,16 +12,16 @@ examples/images.rb
|
|
12
12
|
examples/test.rtf
|
13
13
|
examples/using_a_block.rb
|
14
14
|
lib/reportbuilder.rb
|
15
|
-
lib/reportbuilder/
|
16
|
-
lib/reportbuilder/
|
17
|
-
lib/reportbuilder/
|
18
|
-
lib/reportbuilder/
|
15
|
+
lib/reportbuilder/builder.rb
|
16
|
+
lib/reportbuilder/builder/html.rb
|
17
|
+
lib/reportbuilder/builder/rtf.rb
|
18
|
+
lib/reportbuilder/builder/text.rb
|
19
19
|
lib/reportbuilder/image.rb
|
20
20
|
lib/reportbuilder/section.rb
|
21
21
|
lib/reportbuilder/table.rb
|
22
|
-
lib/reportbuilder/table/
|
23
|
-
lib/reportbuilder/table/
|
24
|
-
lib/reportbuilder/table/
|
22
|
+
lib/reportbuilder/table/htmlbuilder.rb
|
23
|
+
lib/reportbuilder/table/rtfbuilder.rb
|
24
|
+
lib/reportbuilder/table/textbuilder.rb
|
25
25
|
test/test_html.rb
|
26
26
|
test/test_image.rb
|
27
27
|
test/test_reportbuilder.rb
|
data/Rakefile
CHANGED
@@ -12,8 +12,15 @@ Hoe.spec 'reportbuilder' do
|
|
12
12
|
self.rubyforge_name = 'ruby-statsample'
|
13
13
|
self.developer('Claudio Bustos', 'clbustos_at_gmail.com')
|
14
14
|
self.url = "http://ruby-statsample.rubyforge.org/reportbuilder/"
|
15
|
-
self.extra_deps << ["clbustos-rtf","~>0.2.1"]
|
16
|
-
self.extra_dev_deps << ["
|
15
|
+
self.extra_deps << ["clbustos-rtf","~>0.2.1"] << ['text-table', "~>1.2"]
|
16
|
+
self.extra_dev_deps << ["nokogiri", "~>1.4"]
|
17
|
+
end
|
18
|
+
|
19
|
+
task :release => [:tag] do
|
20
|
+
end
|
21
|
+
|
22
|
+
task :tag do
|
23
|
+
sh %(svn cp https://ruby-statsample.googlecode.com/svn/reportbuilder/trunk https://ruby-statsample.googlecode.com/svn/reportbuilder/tags/v#{ReportBuilder::VERSION} -m "ReportBuilder #{ReportBuilder::VERSION} tagged")
|
17
24
|
end
|
18
25
|
|
19
26
|
# vim: syntax=ruby
|
data/lib/reportbuilder.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
+
require 'reportbuilder/builder'
|
1
2
|
require 'reportbuilder/table'
|
2
3
|
require 'reportbuilder/section'
|
3
|
-
require 'reportbuilder/generator'
|
4
4
|
require 'reportbuilder/image'
|
5
|
+
|
5
6
|
# = Report Abstract Interface.
|
6
|
-
# Creates text and
|
7
|
+
# Creates text, html and rtf output, based on a common framework.
|
8
|
+
#
|
7
9
|
# == Use
|
8
10
|
#
|
9
11
|
#
|
@@ -26,7 +28,7 @@ require 'reportbuilder/image'
|
|
26
28
|
# rb.name="Html output"
|
27
29
|
# puts rb.to_html
|
28
30
|
#
|
29
|
-
# * Using a block, you can control directly the
|
31
|
+
# * Using a block, you can control directly the builder
|
30
32
|
#
|
31
33
|
# require "reportbuilder"
|
32
34
|
# rb=ReportBuilder.new do
|
@@ -50,7 +52,15 @@ class ReportBuilder
|
|
50
52
|
attr_accessor :name
|
51
53
|
# Doesn't print a title if set to true
|
52
54
|
attr_accessor :no_title
|
53
|
-
|
55
|
+
# ReportBuilder version
|
56
|
+
VERSION = '1.2.0'
|
57
|
+
|
58
|
+
FormatNotFound=Class.new(Exception)
|
59
|
+
# Available formats
|
60
|
+
def self.builder_for(format)
|
61
|
+
format=format.to_s.downcase
|
62
|
+
Builder.inherited_classes.find {|m| m.code.include? format}
|
63
|
+
end
|
54
64
|
# Generates and optionally save the report on one function
|
55
65
|
def self.generate(options=Hash.new, &block)
|
56
66
|
options[:filename]||=nil
|
@@ -58,18 +68,18 @@ class ReportBuilder
|
|
58
68
|
|
59
69
|
if options[:filename] and options[:filename]=~/\.(\w+?)$/
|
60
70
|
options[:format]=$1
|
61
|
-
options[:format]="text" if options[:format]=="txt"
|
62
71
|
end
|
63
72
|
file=options.delete(:filename)
|
64
|
-
format=options.delete(:format)
|
65
|
-
format[0]=format[0,1].upcase
|
73
|
+
format=options.delete(:format)
|
66
74
|
rb=ReportBuilder.new(options)
|
67
|
-
|
68
75
|
rb.add(block)
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
76
|
+
begin
|
77
|
+
builder=builder_for(format).new(rb, options)
|
78
|
+
rescue NameError => e
|
79
|
+
raise FormatNotFound.new(e)
|
80
|
+
end
|
81
|
+
builder.parse
|
82
|
+
out=builder.out
|
73
83
|
unless file.nil?
|
74
84
|
File.open(file,"wb") do |fp|
|
75
85
|
fp.write out
|
@@ -96,19 +106,19 @@ class ReportBuilder
|
|
96
106
|
end
|
97
107
|
# Returns an Html output
|
98
108
|
def to_html()
|
99
|
-
gen =
|
109
|
+
gen = Builder::Html.new(self,@options)
|
100
110
|
gen.parse
|
101
111
|
gen.out
|
102
112
|
end
|
103
113
|
# Returns a RTF output
|
104
114
|
def to_rtf()
|
105
|
-
gen =
|
115
|
+
gen = Builder::Rtf.new(self, @options)
|
106
116
|
gen.parse
|
107
117
|
gen.out
|
108
118
|
end
|
109
119
|
# Save a rtf file
|
110
120
|
def save_rtf(filename)
|
111
|
-
gen =
|
121
|
+
gen = Builder::Rtf.new(self,@options)
|
112
122
|
gen.parse
|
113
123
|
gen.save(filename)
|
114
124
|
end
|
@@ -116,13 +126,13 @@ class ReportBuilder
|
|
116
126
|
def save_html(file)
|
117
127
|
options=@options.dup
|
118
128
|
options[:directory]=File.dirname(file)
|
119
|
-
gen=
|
129
|
+
gen=Builder::Html.new(self, options)
|
120
130
|
gen.parse
|
121
131
|
gen.save(file)
|
122
132
|
end
|
123
133
|
# Returns a Text output
|
124
134
|
def to_text()
|
125
|
-
gen=
|
135
|
+
gen=Builder::Text.new(self, @options)
|
126
136
|
gen.parse
|
127
137
|
gen.out
|
128
138
|
end
|
@@ -1,15 +1,27 @@
|
|
1
1
|
class ReportBuilder
|
2
|
-
# Abstract
|
3
|
-
# A
|
2
|
+
# Abstract Builder.
|
3
|
+
# A builder is a class which control the output for a ReportBuilder object
|
4
4
|
# Every object which have a #report_building() method could be
|
5
5
|
# parsed with #parse_element method.
|
6
|
-
class
|
6
|
+
class Builder
|
7
7
|
# Level of heading. See ReportBuilder::Section for using it.
|
8
8
|
attr_reader :parse_level
|
9
|
-
# Options for
|
9
|
+
# Options for Builder. Passed by ReportBuilder class on creation
|
10
10
|
attr_reader :options
|
11
11
|
# Entries for Table of Contents
|
12
12
|
attr_reader :toc
|
13
|
+
# Array of string with format names for the Builder.
|
14
|
+
# For example, Html builder returns %w{html htm} and
|
15
|
+
# Text builde returns %w{text txt}
|
16
|
+
def self.code
|
17
|
+
# raise "Implement this"
|
18
|
+
end
|
19
|
+
def self.inherited_classes
|
20
|
+
@@inherited_classes||=Array.new
|
21
|
+
end
|
22
|
+
def self.inherited(subclass)
|
23
|
+
inherited_classes << subclass
|
24
|
+
end
|
13
25
|
def initialize(builder, options)
|
14
26
|
@builder=builder
|
15
27
|
@parse_level=0
|
@@ -24,7 +36,7 @@ class ReportBuilder
|
|
24
36
|
def parse
|
25
37
|
parse_cycle(@builder)
|
26
38
|
end
|
27
|
-
# Save the output of
|
39
|
+
# Save the output of builder to a file
|
28
40
|
def save(filename)
|
29
41
|
File.open(filename, "wb") do |fp|
|
30
42
|
fp.write(out)
|
@@ -35,7 +47,7 @@ class ReportBuilder
|
|
35
47
|
Hash.new
|
36
48
|
end
|
37
49
|
|
38
|
-
# Parse each
|
50
|
+
# Parse each #elements of the container
|
39
51
|
def parse_cycle(container)
|
40
52
|
@parse_level+=1
|
41
53
|
container.elements.each do |element|
|
@@ -46,14 +58,15 @@ class ReportBuilder
|
|
46
58
|
|
47
59
|
# Parse one object, using this workflow
|
48
60
|
# * If is a block, evaluate it
|
49
|
-
# * Use #
|
61
|
+
# * Use #report_building_CODE, where CODE is one of the codes defined by #code
|
50
62
|
# * Use #report_building
|
51
63
|
# * Use #to_s
|
52
64
|
def parse_element(element)
|
53
|
-
|
65
|
+
methods=self.class.code.map {|m| ("report_building_"+m).intern}
|
66
|
+
|
54
67
|
if element.is_a? Proc
|
55
68
|
element.arity<1 ? instance_eval(&element) : element.call(self)
|
56
|
-
elsif element.respond_to?
|
69
|
+
elsif method=methods.find {|m| element.respond_to? m}
|
57
70
|
element.send(method, self)
|
58
71
|
elsif element.respond_to? :report_building
|
59
72
|
element.send(:report_building, self)
|
@@ -78,7 +91,7 @@ class ReportBuilder
|
|
78
91
|
def text(t)
|
79
92
|
raise "Implement this"
|
80
93
|
end
|
81
|
-
# Add html code. Only parsed with
|
94
|
+
# Add html code. Only parsed with builder which understand html
|
82
95
|
def html(t)
|
83
96
|
raise "Implement this"
|
84
97
|
end
|
@@ -105,15 +118,15 @@ class ReportBuilder
|
|
105
118
|
end
|
106
119
|
end
|
107
120
|
|
108
|
-
class
|
109
|
-
def initialize(
|
121
|
+
class ElementBuilder
|
122
|
+
def initialize(builder,element)
|
110
123
|
@element=element
|
111
|
-
@
|
124
|
+
@builder=builder
|
112
125
|
end
|
113
126
|
end
|
114
127
|
end
|
115
128
|
|
116
|
-
require 'reportbuilder/
|
117
|
-
require 'reportbuilder/
|
118
|
-
require 'reportbuilder/
|
129
|
+
require 'reportbuilder/builder/text'
|
130
|
+
require 'reportbuilder/builder/html'
|
131
|
+
require 'reportbuilder/builder/rtf'
|
119
132
|
|
@@ -1,8 +1,7 @@
|
|
1
1
|
require 'fileutils'
|
2
2
|
class ReportBuilder
|
3
|
-
class
|
4
|
-
class Html <
|
5
|
-
PREFIX="html"
|
3
|
+
class Builder
|
4
|
+
class Html < Builder
|
6
5
|
attr_reader :directory
|
7
6
|
def initialize(builder, options)
|
8
7
|
super
|
@@ -11,6 +10,11 @@ class ReportBuilder
|
|
11
10
|
@headers=[]
|
12
11
|
@footers=[]
|
13
12
|
end
|
13
|
+
|
14
|
+
def self.code
|
15
|
+
%w{html htm}
|
16
|
+
end
|
17
|
+
|
14
18
|
def default_options
|
15
19
|
{:directory => Dir.pwd}
|
16
20
|
end
|
@@ -1,13 +1,11 @@
|
|
1
|
-
gem 'clbustos-rtf'
|
2
1
|
require 'rtf'
|
3
|
-
|
2
|
+
require 'pp'
|
4
3
|
class ReportBuilder
|
5
|
-
class
|
6
|
-
# Rtf
|
4
|
+
class Builder
|
5
|
+
# Rtf Builder.
|
7
6
|
# Based on ruby-rtf (http://ruby-rtf.rubyforge.org/)
|
8
7
|
#
|
9
|
-
class Rtf <
|
10
|
-
PREFIX="rtf"
|
8
|
+
class Rtf < Builder
|
11
9
|
# RTF::Document object.
|
12
10
|
# See http://ruby-rtf.rubyforge.org/ for documentation
|
13
11
|
attr_accessor :rtf
|
@@ -34,6 +32,12 @@ class ReportBuilder
|
|
34
32
|
h[k]={:cs=>cs, :ps=>ps}
|
35
33
|
}
|
36
34
|
end
|
35
|
+
|
36
|
+
def self.code
|
37
|
+
%w{rtf}
|
38
|
+
end
|
39
|
+
|
40
|
+
|
37
41
|
def default_options
|
38
42
|
|
39
43
|
{
|
@@ -1,13 +1,17 @@
|
|
1
1
|
class ReportBuilder
|
2
|
-
class
|
3
|
-
class Text <
|
4
|
-
PREFIX="text"
|
2
|
+
class Builder
|
3
|
+
class Text < Builder
|
5
4
|
attr_reader :toc
|
6
5
|
attr_reader :out
|
7
6
|
def initialize(builder, options)
|
8
7
|
super
|
9
8
|
@out=""
|
10
9
|
end
|
10
|
+
|
11
|
+
def self.code
|
12
|
+
%w{text txt}
|
13
|
+
end
|
14
|
+
|
11
15
|
def parse
|
12
16
|
@out="#{@builder.name}\n" unless @builder.no_title
|
13
17
|
parse_cycle(@builder)
|
data/lib/reportbuilder/image.rb
CHANGED
@@ -21,7 +21,7 @@ class ReportBuilder::Image
|
|
21
21
|
@filename=filename
|
22
22
|
end
|
23
23
|
# Based on http://rubyquiz.com/quiz50.html
|
24
|
-
def report_building_text(
|
24
|
+
def report_building_text(builder)
|
25
25
|
require 'RMagick'
|
26
26
|
|
27
27
|
|
@@ -69,14 +69,14 @@ class ReportBuilder::Image
|
|
69
69
|
end
|
70
70
|
end
|
71
71
|
out+= border
|
72
|
-
|
72
|
+
builder.preformatted(out)
|
73
73
|
end
|
74
|
-
def report_building_rtf(
|
75
|
-
raise "Not implemented on RTF::Document. Use gem install thecrisoshow-ruby-rtf for support" unless
|
76
|
-
|
74
|
+
def report_building_rtf(builder)
|
75
|
+
raise "Not implemented on RTF::Document. Use gem install thecrisoshow-ruby-rtf for support" unless builder.rtf.respond_to? :image
|
76
|
+
builder.rtf.image(@filename)
|
77
77
|
end
|
78
|
-
def report_building_html(
|
79
|
-
basedir=
|
78
|
+
def report_building_html(builder)
|
79
|
+
basedir=builder.directory+"/images"
|
80
80
|
out=basedir+"/"+File.basename(@filename)
|
81
81
|
if(File.exists? @filename)
|
82
82
|
if !File.exists? out
|
@@ -84,6 +84,6 @@ class ReportBuilder::Image
|
|
84
84
|
FileUtils.cp @filename, out
|
85
85
|
end
|
86
86
|
end
|
87
|
-
|
87
|
+
builder.html("<img src='images/#{File.basename(@filename)}' alt='#{@options[:alt]}' />")
|
88
88
|
end
|
89
89
|
end
|
@@ -26,9 +26,9 @@ class ReportBuilder::Section
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
def report_building_text(
|
30
|
-
|
31
|
-
|
29
|
+
def report_building_text(builder)
|
30
|
+
builder.text(("="*builder.parse_level)+" "+name)
|
31
|
+
builder.parse_cycle(self)
|
32
32
|
end
|
33
33
|
|
34
34
|
def report_building_html(g)
|
data/lib/reportbuilder/table.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
|
1
2
|
class ReportBuilder
|
2
3
|
# Creates a table.
|
3
4
|
# Use:
|
@@ -52,6 +53,7 @@ class ReportBuilder
|
|
52
53
|
end
|
53
54
|
end
|
54
55
|
# Adds a row
|
56
|
+
# <b>Usage:</b>
|
55
57
|
# table.add_row(%w{1 2})
|
56
58
|
def row(row)
|
57
59
|
@rows.push(row)
|
@@ -105,20 +107,20 @@ class ReportBuilder
|
|
105
107
|
}
|
106
108
|
@max_cols
|
107
109
|
end
|
108
|
-
def report_building_text(
|
109
|
-
require 'reportbuilder/table/
|
110
|
-
|
111
|
-
|
110
|
+
def report_building_text(builder)
|
111
|
+
require 'reportbuilder/table/textbuilder'
|
112
|
+
table_builder=ReportBuilder::Table::TextBuilder.new( builder, self)
|
113
|
+
table_builder.generate
|
112
114
|
end
|
113
|
-
def report_building_html(
|
114
|
-
require 'reportbuilder/table/
|
115
|
-
|
116
|
-
|
115
|
+
def report_building_html(builder)
|
116
|
+
require 'reportbuilder/table/htmlbuilder'
|
117
|
+
table_builder=ReportBuilder::Table::HtmlBuilder.new(builder, self)
|
118
|
+
table_builder.generate
|
117
119
|
end
|
118
|
-
def report_building_rtf(
|
119
|
-
require 'reportbuilder/table/
|
120
|
-
|
121
|
-
|
120
|
+
def report_building_rtf(builder)
|
121
|
+
require 'reportbuilder/table/rtfbuilder'
|
122
|
+
table_builder=ReportBuilder::Table::RtfBuilder.new(builder, self)
|
123
|
+
table_builder.generate
|
122
124
|
end
|
123
125
|
def total_width # :nodoc:
|
124
126
|
if @max_cols.size>0
|
@@ -127,6 +129,9 @@ class ReportBuilder
|
|
127
129
|
0
|
128
130
|
end
|
129
131
|
end
|
132
|
+
|
133
|
+
|
134
|
+
|
130
135
|
######################
|
131
136
|
# INTERNAL CLASSES #
|
132
137
|
######################
|
@@ -154,4 +159,7 @@ class ReportBuilder
|
|
154
159
|
end
|
155
160
|
end
|
156
161
|
end
|
162
|
+
require 'reportbuilder/table/htmlbuilder'
|
163
|
+
require 'reportbuilder/table/textbuilder'
|
164
|
+
require 'reportbuilder/table/rtfbuilder'
|
157
165
|
|
@@ -1,9 +1,9 @@
|
|
1
1
|
class ReportBuilder
|
2
2
|
class Table
|
3
|
-
class
|
3
|
+
class HtmlBuilder < ElementBuilder
|
4
4
|
def generate()
|
5
5
|
t=@element
|
6
|
-
anchor=@
|
6
|
+
anchor=@builder.table_entry(t.name)
|
7
7
|
out="<a name='#{anchor}'></a><table><caption>#{t.name}</caption>"
|
8
8
|
@rowspans=[]
|
9
9
|
if t.header.size>0
|
@@ -21,27 +21,31 @@ class ReportBuilder
|
|
21
21
|
end
|
22
22
|
}
|
23
23
|
out+="</tbody>\n</table>\n"
|
24
|
-
@
|
24
|
+
@builder.html(out)
|
25
25
|
end
|
26
26
|
def parse_row(t,row,tag="td")
|
27
27
|
row_ary=[]
|
28
|
-
|
28
|
+
real_i=0
|
29
29
|
row.each_index do |i|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
30
|
+
extra=1
|
31
|
+
while !@rowspans[real_i].nil? and @rowspans[real_i]>0
|
32
|
+
@rowspans[real_i]-=1
|
33
|
+
row_ary << ""
|
34
|
+
real_i+=1
|
35
|
+
end
|
36
|
+
|
37
|
+
if row[i].is_a? Table::Colspan
|
35
38
|
row_ary.push(sprintf("<%s colspan=\"%d\">%s</%s>",tag, row[i].cols, row[i].data,tag))
|
36
|
-
colspan_i=row[i].cols-1
|
37
39
|
elsif row[i].nil?
|
38
40
|
row_ary.push("<#{tag}></#{tag}>")
|
39
41
|
elsif row[i].is_a? Table::Rowspan
|
40
42
|
row_ary.push(sprintf("<%s rowspan=\"%d\">%s</%s>", tag, row[i].rows, row[i].data, tag))
|
41
|
-
@rowspans[
|
43
|
+
@rowspans[real_i]=row[i].rows-1
|
42
44
|
else
|
43
45
|
row_ary.push("<#{tag}>#{row[i]}</#{tag}>")
|
44
46
|
end
|
47
|
+
real_i+=extra
|
48
|
+
|
45
49
|
end
|
46
50
|
row_ary.join("")
|
47
51
|
end
|
@@ -1,20 +1,20 @@
|
|
1
1
|
class ReportBuilder
|
2
2
|
class Table
|
3
|
-
class
|
3
|
+
class RtfBuilder < ElementBuilder
|
4
4
|
include RTF
|
5
5
|
def generate()
|
6
6
|
@t=@element
|
7
|
-
@rtf=@
|
7
|
+
@rtf=@builder.rtf
|
8
8
|
|
9
9
|
# Title
|
10
10
|
|
11
|
-
@
|
11
|
+
@builder.header(6,@t.name)
|
12
12
|
|
13
13
|
max_cols=@t.calculate_widths
|
14
14
|
n_rows=@t.n_rows_no_hr+(@t.header.size>0 ? 1: 0)
|
15
|
-
args=[n_rows, @t.n_columns]+max_cols.map{|m| m*@
|
15
|
+
args=[n_rows, @t.n_columns]+max_cols.map{|m| m*@builder.options[:font_size]*10}
|
16
16
|
@table=@rtf.table(*args)
|
17
|
-
@table.border_width=@
|
17
|
+
@table.border_width=@builder.options[:table_border_width]
|
18
18
|
@rowspans=[]
|
19
19
|
if @t.header.size>0
|
20
20
|
@t.header.each_with_index do |th,i|
|
@@ -40,30 +40,34 @@ class ReportBuilder
|
|
40
40
|
end
|
41
41
|
def create_hr(row_i)
|
42
42
|
(0...@t.n_columns).each {|i|
|
43
|
-
@table[row_i][i].top_border_width=@
|
43
|
+
@table[row_i][i].top_border_width=@builder.options[:table_hr_width]
|
44
44
|
}
|
45
45
|
end
|
46
46
|
|
47
47
|
def parse_row(row,row_i)
|
48
48
|
t=@element
|
49
49
|
row_ary=[]
|
50
|
+
real_i=0
|
50
51
|
colspan_i=0
|
51
52
|
row.each_index do |i|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
53
|
+
extra=1
|
54
|
+
while !@rowspans[real_i].nil? and @rowspans[real_i]>0
|
55
|
+
@rowspans[real_i]-=1
|
56
|
+
real_i+=1
|
57
|
+
end
|
58
|
+
if row[i].is_a? Table::Colspan
|
59
|
+
@table[row_i][real_i] << row[i].data
|
58
60
|
colspan_i=row[i].cols-1
|
61
|
+
extra=row[i].cols
|
59
62
|
elsif row[i].nil?
|
60
63
|
@table[row_i][i] << ""
|
61
64
|
elsif row[i].is_a? Table::Rowspan
|
62
|
-
@table[row_i][
|
63
|
-
@rowspans[
|
65
|
+
@table[row_i][real_i] << row[i].data
|
66
|
+
@rowspans[real_i]=row[i].rows-1
|
64
67
|
else
|
65
|
-
@table[row_i][
|
68
|
+
@table[row_i][real_i] << row[i].to_s
|
66
69
|
end
|
70
|
+
real_i+=extra
|
67
71
|
end
|
68
72
|
end
|
69
73
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'text-table'
|
2
|
+
class ReportBuilder
|
3
|
+
class Table
|
4
|
+
class TextBuilder < ElementBuilder
|
5
|
+
def generate()
|
6
|
+
|
7
|
+
t=@element
|
8
|
+
@rowspans=[]
|
9
|
+
@builder.text(t.name)
|
10
|
+
return if t.header.size+t.rows.size==0
|
11
|
+
table = Text::Table.new do |tt|
|
12
|
+
tt.head=t.header if t.header.size>0
|
13
|
+
tt.rows=t.rows.map {|row| parse_row(row)}
|
14
|
+
end
|
15
|
+
#pp table.rows
|
16
|
+
@builder.text(table.to_s)
|
17
|
+
end
|
18
|
+
# Parse a row
|
19
|
+
def parse_row(row)
|
20
|
+
return :separator if row==:hr
|
21
|
+
t=@element
|
22
|
+
row_ary=[]
|
23
|
+
real_i=0
|
24
|
+
row.each_index do |i|
|
25
|
+
extra=1
|
26
|
+
|
27
|
+
while !@rowspans[real_i].nil? and @rowspans[real_i]>0
|
28
|
+
@rowspans[real_i]-=1
|
29
|
+
row_ary << ""
|
30
|
+
real_i+=1
|
31
|
+
end
|
32
|
+
|
33
|
+
if row[i].is_a? ReportBuilder::Table::Rowspan
|
34
|
+
@rowspans[real_i]=row[i].rows-1
|
35
|
+
row_ary << row[i].to_s
|
36
|
+
elsif row[i].is_a? ReportBuilder::Table::Colspan
|
37
|
+
row_ary.push({:value=>row[i].to_s, :colspan=>row[i].cols})
|
38
|
+
extra=row[i].cols
|
39
|
+
elsif row[i].nil?
|
40
|
+
row_ary.push("")
|
41
|
+
else
|
42
|
+
#size=row[i].to_s.size
|
43
|
+
#puts sprintf("%i : %s (%d-%d)",i,row[i].to_s,@max_cols[i], size)
|
44
|
+
row_ary.push(row[i].to_s)
|
45
|
+
end
|
46
|
+
real_i+=extra
|
47
|
+
end
|
48
|
+
row_ary
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/test/test_image.rb
CHANGED
@@ -41,6 +41,6 @@ Test
|
|
41
41
|
assert_match(/img src='images\/sheep.jpg'/, @rp.to_html)
|
42
42
|
end
|
43
43
|
def test_image_rtf
|
44
|
-
assert_match(/\\pict\\picw128\\pich112\\
|
44
|
+
assert_match(/\\pict\\picw128\\pich112\\bliptag\d+\\jpegblip/, @rp.to_rtf)
|
45
45
|
end
|
46
46
|
end
|
data/test/test_reportbuilder.rb
CHANGED
@@ -64,6 +64,8 @@ class TestReportbuilder < MiniTest::Unit::TestCase
|
|
64
64
|
["para","pre","th1","th2"].each do |t|
|
65
65
|
assert_match(/#{t}/,out)
|
66
66
|
end
|
67
|
+
|
68
|
+
|
67
69
|
end
|
68
70
|
def test_empty
|
69
71
|
rp=ReportBuilder.new
|
@@ -73,11 +75,32 @@ class TestReportbuilder < MiniTest::Unit::TestCase
|
|
73
75
|
rp.add("hola")
|
74
76
|
assert_equal("hola\n",rp.to_s)
|
75
77
|
end
|
78
|
+
def test_incorrect_format
|
79
|
+
assert_raises ReportBuilder::FormatNotFound do
|
80
|
+
ReportBuilder::generate(:format=>:fish) do
|
81
|
+
text "This is silly"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
def test_formats
|
86
|
+
require 'pp'
|
87
|
+
assert_equal(ReportBuilder.builder_for(:txt), ReportBuilder::Builder::Text)
|
88
|
+
assert_equal(ReportBuilder.builder_for("txt"), ReportBuilder::Builder::Text)
|
89
|
+
assert_equal(ReportBuilder.builder_for("html"), ReportBuilder::Builder::Html)
|
90
|
+
|
91
|
+
end
|
92
|
+
|
76
93
|
def test_generate
|
77
|
-
|
94
|
+
txt_file=Tempfile.new("test.txt")
|
95
|
+
ReportBuilder.generate(:name=>"Test", :filename=>txt_file.path) do
|
96
|
+
text("hola")
|
97
|
+
end
|
98
|
+
|
99
|
+
text=ReportBuilder.generate(:format=>:text,:name=>"Test") do
|
78
100
|
text("hola")
|
79
101
|
end
|
80
|
-
assert_match(/^Test\nhola$/,
|
102
|
+
assert_match(/^Test\nhola$/,text)
|
103
|
+
assert_equal(text, File.read(txt_file.path))
|
81
104
|
html_file=Tempfile.new("test.html")
|
82
105
|
html=ReportBuilder.generate(:name=>"Test", :format=>:html) do
|
83
106
|
text("hola")
|
data/test/test_table.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
require "minitest/unit"
|
2
2
|
$:.unshift(File.dirname(__FILE__)+"/../lib")
|
3
3
|
require "reportbuilder"
|
4
|
-
require 'reportbuilder/table/htmlgenerator'
|
5
|
-
require 'reportbuilder/table/textgenerator'
|
6
4
|
require 'nokogiri'
|
7
5
|
|
8
6
|
MiniTest::Unit.autorun
|
@@ -11,13 +9,13 @@ class TestReportbuilderTable < MiniTest::Unit::TestCase
|
|
11
9
|
super
|
12
10
|
@name="Table Test"
|
13
11
|
@header=%w{a bb ccc dddd eeee fff gggg hh i}
|
14
|
-
table=ReportBuilder::Table.new(:name
|
12
|
+
table=ReportBuilder::Table.new(:name=>@name, :header=>@header) do
|
15
13
|
row(["a","b","c","d","e","f","g","h","i"])
|
16
|
-
row([colspan("a",2),
|
17
|
-
row([colspan("a",3),
|
18
|
-
row([colspan("a",4),
|
19
|
-
row([colspan("a",5),
|
20
|
-
row([colspan("a",6),
|
14
|
+
row([colspan("a",2),"c",'d',rowspan("e",2),rowspan("f",2),"g",rowspan("h",3),"i"])
|
15
|
+
row([colspan("a",3),'d', "g","i"])
|
16
|
+
row([colspan("a",4),"e","f","g","i"])
|
17
|
+
row([colspan("a",5),colspan("f",3),"i"])
|
18
|
+
row([colspan("a",6),"g","h","i"])
|
21
19
|
end
|
22
20
|
|
23
21
|
@table=table
|
@@ -25,16 +23,25 @@ class TestReportbuilderTable < MiniTest::Unit::TestCase
|
|
25
23
|
@mock_generator = ""
|
26
24
|
class << @mock_generator
|
27
25
|
def preformatted(t)
|
28
|
-
|
26
|
+
@first_pre||=true
|
27
|
+
self << "\n" unless @first_pre
|
28
|
+
self << t
|
29
|
+
@first=false
|
29
30
|
end
|
30
31
|
def text(t)
|
31
|
-
|
32
|
+
@first_text||=:true
|
33
|
+
self << "\n" unless @first_text==:true
|
34
|
+
self << t
|
35
|
+
@first_text=:false
|
32
36
|
end
|
33
37
|
def table_entry(t)
|
34
38
|
"MOCK"
|
35
39
|
end
|
36
40
|
def html(t)
|
37
|
-
|
41
|
+
@first_html||=true
|
42
|
+
self << "\n" unless @first_html
|
43
|
+
self << t
|
44
|
+
@first=false
|
38
45
|
end
|
39
46
|
end
|
40
47
|
|
@@ -45,75 +52,69 @@ class TestReportbuilderTable < MiniTest::Unit::TestCase
|
|
45
52
|
end
|
46
53
|
assert_match(/^Table\s+$/ , text)
|
47
54
|
end
|
55
|
+
|
56
|
+
def test_rtf
|
57
|
+
rb=ReportBuilder.new
|
58
|
+
rb.add(@table)
|
59
|
+
rb.save_rtf("test.rtf")
|
60
|
+
|
61
|
+
|
62
|
+
end
|
48
63
|
def test_table_text
|
49
|
-
|
50
|
-
tg=ReportBuilder::Table::TextGenerator.new(@mock_generator,@table)
|
64
|
+
tg=ReportBuilder::Table::TextBuilder.new(@mock_generator, @table)
|
51
65
|
tg.generate
|
52
|
-
|
66
|
+
expected= <<-HEREDOC
|
53
67
|
Table Test
|
54
|
-
|
68
|
+
+---+----+-----+------+------+-----+------+----+---+
|
55
69
|
| a | bb | ccc | dddd | eeee | fff | gggg | hh | i |
|
56
|
-
|
70
|
+
+---+----+-----+------+------+-----+------+----+---+
|
57
71
|
| a | b | c | d | e | f | g | h | i |
|
58
72
|
| a | c | d | e | f | g | h | i |
|
59
|
-
| a |
|
60
|
-
| a | e | f | g |
|
73
|
+
| a | d | | | g | | i |
|
74
|
+
| a | e | f | g | | i |
|
61
75
|
| a | f | i |
|
62
76
|
| a | g | h | i |
|
63
|
-
|
77
|
+
+---+----+-----+------+------+-----+------+----+---+
|
64
78
|
HEREDOC
|
65
|
-
|
66
|
-
|
67
|
-
|
79
|
+
#puts expected
|
80
|
+
#puts @mock_generator
|
81
|
+
assert_equal(expected, @mock_generator)
|
68
82
|
end
|
69
83
|
def test_table_html
|
70
84
|
|
71
|
-
tg=ReportBuilder::Table::
|
85
|
+
tg=ReportBuilder::Table::HtmlBuilder.new(@mock_generator,@table)
|
72
86
|
tg.generate
|
73
|
-
|
74
|
-
expected= <<HEREDOC
|
75
|
-
<a name='MOCK'> </a>
|
76
|
-
<table>
|
77
|
-
<thead>
|
78
|
-
<th>a</th><th>bb</th><th>ccc</th>
|
79
|
-
<th>dddd</th><th>eeee</th>
|
80
|
-
<th>fff</th><th>gggg</th><th>hh</th><th>i</th>
|
81
|
-
</thead>
|
82
|
-
<tbody>
|
83
|
-
<tr><td>a</td><td>b</td><td>c</td><td>d</td><td>e</td>
|
84
|
-
<td>f</td><td>g</td><td>h</td><td>i</td></tr>
|
85
|
-
|
86
|
-
<tr><td colspan="2">a</td><td>c</td><td rowspan="2">d</td><td>e</td>
|
87
|
-
<td>f</td><td>g</td><td>h</td><td>i</td></tr>
|
88
|
-
|
89
|
-
<tr><td colspan="3">a</td><td>e</td>
|
90
|
-
<td>f</td><td>g</td><td>h</td><td>i</td></tr>
|
91
|
-
|
92
|
-
<tr><td colspan="4">a</td><td>e</td>
|
93
|
-
<td>f</td><td>g</td><td>h</td><td>i</td></tr>
|
94
|
-
|
95
|
-
<tr><td colspan="5">a</td><td colspan="3">f</td><td>i</td></tr>
|
96
|
-
|
97
|
-
<tr><td colspan="6">a</td><td>g</td><td>h</td><td>i</td></tr>
|
98
|
-
</tbody>
|
99
|
-
</table>
|
100
|
-
HEREDOC
|
101
|
-
|
102
87
|
doc=Nokogiri::HTML(@mock_generator).at_xpath("/html")
|
103
88
|
|
104
89
|
assert(doc.at_xpath("a[@name='MOCK']")!="")
|
105
90
|
assert(doc.at_xpath("table")!="")
|
106
91
|
|
107
92
|
assert_equal(@header, doc.xpath("//table/thead/th").map {|m| m.content} )
|
108
|
-
[
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
93
|
+
expected_contents=[
|
94
|
+
%w{a b c d e f g h i},
|
95
|
+
%w{a c d e f g h i},
|
96
|
+
%w{a d g i},
|
97
|
+
%w{a e f g i},
|
98
|
+
%w{a f i},
|
99
|
+
%w{a g h i}
|
100
|
+
]
|
101
|
+
real_contents=doc.xpath("//table/tbody/tr").map do |tr|
|
102
|
+
tds=tr.xpath("td").map {|m| m.content}
|
103
|
+
|
104
|
+
end
|
105
|
+
assert_equal(expected_contents, real_contents)
|
113
106
|
|
114
|
-
|
115
|
-
|
116
|
-
|
107
|
+
[
|
108
|
+
['colspan',2,%w{a}],
|
109
|
+
['colspan',3,%w{a f}],
|
110
|
+
['colspan',4,%w{a}],
|
111
|
+
['colspan',5,%w{a}],
|
112
|
+
['colspan',6,%w{a}],
|
113
|
+
['rowspan',2,%w{e f}],
|
114
|
+
['rowspan',3,%w{h}],
|
115
|
+
].each do |attr,m,exp|
|
116
|
+
real=doc.xpath("//table/tbody/tr/td[@#{attr}='#{m}']").map {|x| x.content}.sort
|
117
|
+
assert_equal(exp, real, "On table/tbody/tr/td[@#{attr}='#{m}']"
|
117
118
|
)
|
118
119
|
end
|
119
120
|
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: reportbuilder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 1
|
7
|
+
- 2
|
8
|
+
- 0
|
9
|
+
version: 1.2.0
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Claudio Bustos
|
@@ -9,59 +14,91 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date: 2010-03-
|
17
|
+
date: 2010-03-28 00:00:00 -03:00
|
13
18
|
default_executable:
|
14
19
|
dependencies:
|
15
20
|
- !ruby/object:Gem::Dependency
|
16
21
|
name: clbustos-rtf
|
17
|
-
|
18
|
-
|
19
|
-
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
24
|
requirements:
|
21
25
|
- - ~>
|
22
26
|
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
- 2
|
30
|
+
- 1
|
23
31
|
version: 0.2.1
|
24
|
-
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: text-table
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ~>
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 1
|
43
|
+
- 2
|
44
|
+
version: "1.2"
|
45
|
+
type: :runtime
|
46
|
+
version_requirements: *id002
|
25
47
|
- !ruby/object:Gem::Dependency
|
26
48
|
name: rubyforge
|
27
|
-
|
28
|
-
|
29
|
-
version_requirements: !ruby/object:Gem::Requirement
|
49
|
+
prerelease: false
|
50
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
30
51
|
requirements:
|
31
52
|
- - ">="
|
32
53
|
- !ruby/object:Gem::Version
|
54
|
+
segments:
|
55
|
+
- 2
|
56
|
+
- 0
|
57
|
+
- 4
|
33
58
|
version: 2.0.4
|
34
|
-
|
59
|
+
type: :development
|
60
|
+
version_requirements: *id003
|
35
61
|
- !ruby/object:Gem::Dependency
|
36
62
|
name: gemcutter
|
37
|
-
|
38
|
-
|
39
|
-
version_requirements: !ruby/object:Gem::Requirement
|
63
|
+
prerelease: false
|
64
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
40
65
|
requirements:
|
41
66
|
- - ">="
|
42
67
|
- !ruby/object:Gem::Version
|
68
|
+
segments:
|
69
|
+
- 0
|
70
|
+
- 5
|
71
|
+
- 0
|
43
72
|
version: 0.5.0
|
44
|
-
version:
|
45
|
-
- !ruby/object:Gem::Dependency
|
46
|
-
name: hpricot
|
47
73
|
type: :development
|
48
|
-
|
49
|
-
|
74
|
+
version_requirements: *id004
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: nokogiri
|
77
|
+
prerelease: false
|
78
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
50
79
|
requirements:
|
51
80
|
- - ~>
|
52
81
|
- !ruby/object:Gem::Version
|
53
|
-
|
54
|
-
|
82
|
+
segments:
|
83
|
+
- 1
|
84
|
+
- 4
|
85
|
+
version: "1.4"
|
86
|
+
type: :development
|
87
|
+
version_requirements: *id005
|
55
88
|
- !ruby/object:Gem::Dependency
|
56
89
|
name: hoe
|
57
|
-
|
58
|
-
|
59
|
-
version_requirements: !ruby/object:Gem::Requirement
|
90
|
+
prerelease: false
|
91
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
60
92
|
requirements:
|
61
93
|
- - ">="
|
62
94
|
- !ruby/object:Gem::Version
|
95
|
+
segments:
|
96
|
+
- 2
|
97
|
+
- 5
|
98
|
+
- 1
|
63
99
|
version: 2.5.1
|
64
|
-
|
100
|
+
type: :development
|
101
|
+
version_requirements: *id006
|
65
102
|
description: Report Abstract Interface. Creates text, html and rtf output, based on a common framework.
|
66
103
|
email:
|
67
104
|
- clbustos_at_gmail.com
|
@@ -88,16 +125,16 @@ files:
|
|
88
125
|
- examples/test.rtf
|
89
126
|
- examples/using_a_block.rb
|
90
127
|
- lib/reportbuilder.rb
|
91
|
-
- lib/reportbuilder/
|
92
|
-
- lib/reportbuilder/
|
93
|
-
- lib/reportbuilder/
|
94
|
-
- lib/reportbuilder/
|
128
|
+
- lib/reportbuilder/builder.rb
|
129
|
+
- lib/reportbuilder/builder/html.rb
|
130
|
+
- lib/reportbuilder/builder/rtf.rb
|
131
|
+
- lib/reportbuilder/builder/text.rb
|
95
132
|
- lib/reportbuilder/image.rb
|
96
133
|
- lib/reportbuilder/section.rb
|
97
134
|
- lib/reportbuilder/table.rb
|
98
|
-
- lib/reportbuilder/table/
|
99
|
-
- lib/reportbuilder/table/
|
100
|
-
- lib/reportbuilder/table/
|
135
|
+
- lib/reportbuilder/table/htmlbuilder.rb
|
136
|
+
- lib/reportbuilder/table/rtfbuilder.rb
|
137
|
+
- lib/reportbuilder/table/textbuilder.rb
|
101
138
|
- test/test_html.rb
|
102
139
|
- test/test_image.rb
|
103
140
|
- test/test_reportbuilder.rb
|
@@ -117,18 +154,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
117
154
|
requirements:
|
118
155
|
- - ">="
|
119
156
|
- !ruby/object:Gem::Version
|
157
|
+
segments:
|
158
|
+
- 0
|
120
159
|
version: "0"
|
121
|
-
version:
|
122
160
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
123
161
|
requirements:
|
124
162
|
- - ">="
|
125
163
|
- !ruby/object:Gem::Version
|
164
|
+
segments:
|
165
|
+
- 0
|
126
166
|
version: "0"
|
127
|
-
version:
|
128
167
|
requirements: []
|
129
168
|
|
130
169
|
rubyforge_project: ruby-statsample
|
131
|
-
rubygems_version: 1.3.
|
170
|
+
rubygems_version: 1.3.6
|
132
171
|
signing_key:
|
133
172
|
specification_version: 3
|
134
173
|
summary: Report Abstract Interface
|
@@ -1,55 +0,0 @@
|
|
1
|
-
class ReportBuilder
|
2
|
-
class Table
|
3
|
-
class TextGenerator < ElementGenerator
|
4
|
-
|
5
|
-
def generate()
|
6
|
-
t=@element
|
7
|
-
t.calculate_widths
|
8
|
-
total_width=t.total_width
|
9
|
-
out="#{t.name}\n"
|
10
|
-
if total_width>0
|
11
|
-
if t.header.size>0
|
12
|
-
out+=parse_hr(total_width)+"\n"
|
13
|
-
out+=parse_row(t,t.header)+"\n"
|
14
|
-
out+=parse_hr(total_width)+"\n"
|
15
|
-
end
|
16
|
-
t.rows.each do |row|
|
17
|
-
if row==:hr
|
18
|
-
out+=parse_hr(total_width)+"\n"
|
19
|
-
else
|
20
|
-
out+=parse_row(t,row)+"\n"
|
21
|
-
end
|
22
|
-
end
|
23
|
-
out+=parse_hr(total_width)+"\n"
|
24
|
-
end
|
25
|
-
@generator.text(out)
|
26
|
-
end
|
27
|
-
# Parse a row
|
28
|
-
def parse_row(t,row)
|
29
|
-
row_ary=[]
|
30
|
-
colspan_i=0
|
31
|
-
row.each_index do |i|
|
32
|
-
if colspan_i>0
|
33
|
-
colspan_i-=1
|
34
|
-
elsif row[i].is_a? ReportBuilder::Table::Colspan
|
35
|
-
size = (i...(i+row[i].cols)).inject(0) {|a,v| a+t.max_cols[v]+3}
|
36
|
-
size-=3
|
37
|
-
row_ary.push(row[i].data.to_s+" "*(size - row[i].data.size))
|
38
|
-
colspan_i=row[i].cols-1
|
39
|
-
elsif row[i].nil?
|
40
|
-
row_ary.push(" "*t.max_cols[i])
|
41
|
-
else
|
42
|
-
size=row[i].to_s.size
|
43
|
-
#puts sprintf("%i : %s (%d-%d)",i,row[i].to_s,@max_cols[i], size)
|
44
|
-
row_ary.push(row[i].to_s+" "*(t.max_cols[i] - size))
|
45
|
-
end
|
46
|
-
end
|
47
|
-
"| "+row_ary.join(" | ")+" |"
|
48
|
-
end
|
49
|
-
# Parse a horizontal rule
|
50
|
-
def parse_hr(l)
|
51
|
-
"-"*l
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|