reportbuilder 1.1.1 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|