latex 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +9 -0
- data/README +1 -1
- data/examples/latex.rb +558 -0
- data/examples/latextest.aux +19 -0
- data/examples/latextest.dvi +0 -0
- data/examples/latextest.log +197 -0
- data/examples/latextest.out +0 -0
- data/examples/latextest.tex +91 -0
- data/examples/latextest.tex~ +91 -0
- data/examples/saved_table.dat +1 -0
- data/examples/test-latex.rb +9 -5
- data/examples/test-latex.rb.~1.3.~ +40 -0
- data/lib/latex.rb +64 -22
- metadata +13 -3
data/ChangeLog
ADDED
data/README
CHANGED
data/examples/latex.rb
ADDED
@@ -0,0 +1,558 @@
|
|
1
|
+
# Copyright (c) 2004 Christian Bang <cbang AT web.de> and Frank Hutter
|
2
|
+
#
|
3
|
+
# Version 0.1.2
|
4
|
+
#
|
5
|
+
# All rights reserved. You can redistribute and/or modify it under the same terms as Ruby.
|
6
|
+
#
|
7
|
+
# This file provides a LatexFile class for Ruby.
|
8
|
+
|
9
|
+
class String
|
10
|
+
#Escapes underscores. Use this if you have a string that contains
|
11
|
+
#such but you don't mean the latex semantic of underscore.
|
12
|
+
def escape_
|
13
|
+
gsub(/_/,"\\_")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
#examples: Figure.new("9cm", "image.eps", "Test image")
|
18
|
+
# Figure.new("angle=-90,width=9.5cm", "rotatedimage.eps", "Rotated image", "link01")
|
19
|
+
Figure = Struct.new(:format, :filename, :title, :label)
|
20
|
+
|
21
|
+
class FormatError < StandardError
|
22
|
+
end
|
23
|
+
|
24
|
+
# +LatexFile+ is a +File+ with special functions for easy generation of
|
25
|
+
# LaTeX code.
|
26
|
+
# Current mayor features are +table+ and +figures+ generation.
|
27
|
+
#
|
28
|
+
# You may want to quote underscores ('_') in some Latex code you create. For this use String.escape_ which
|
29
|
+
# is available with this file.
|
30
|
+
class LatexFile < File
|
31
|
+
Header = Struct.new(:name, :align, :children)
|
32
|
+
|
33
|
+
# the default table font size, default is nil which means the Latex default. See #table for possible values
|
34
|
+
attr_accessor :defaultTableFontSize
|
35
|
+
|
36
|
+
@@defaultUsePackages = %w([latin1]{inputenc} [final]{graphics} [pdftex]{graphicx} [dvips]{color}
|
37
|
+
{amsfonts} {subfigure} {lscape} {hyperref})
|
38
|
+
@@default_extras = {:fontsize => "10pt" }
|
39
|
+
attr_reader :extras
|
40
|
+
|
41
|
+
@default_table_align = 'c'
|
42
|
+
# The default table alignment is <tt>'c'</tt> but can be changed.
|
43
|
+
attr_accessor :default_table_align
|
44
|
+
|
45
|
+
# Open a new latex-file for writing.
|
46
|
+
# +extras+ is an optional hash that may contain the following flags
|
47
|
+
# <tt>:landscape</tt>:: turns all pages 90�
|
48
|
+
# <tt>:twocolumn</tt>:: the whole document has two columns
|
49
|
+
# <tt>extras[:fontsize]</tt>:: string containing the font size like "10pt"
|
50
|
+
# === Example:
|
51
|
+
# f = LatexFile.new("test.tex", :twocolumn => true, :fontsize => "11pt")
|
52
|
+
def initialize(filename, extras = nil)
|
53
|
+
super(filename,"w") # open a file for write access
|
54
|
+
@extras = extras || Hash.new
|
55
|
+
#use defaults for unused entries:
|
56
|
+
@@default_extras.each_key{|key| @extras[key] ||= @@default_extras[key] }
|
57
|
+
@indent = 0 # indent lines in blocks
|
58
|
+
|
59
|
+
@usePackages = @extras[:usePackages] || @@defaultUsePackages
|
60
|
+
|
61
|
+
writeDocumentHeader
|
62
|
+
@lastWasPrint = false
|
63
|
+
end
|
64
|
+
|
65
|
+
def writeDocumentHeader
|
66
|
+
twocolumn = @extras[:twocolumn] ? ",twocolumn" : ""
|
67
|
+
landscape = @extras[:landscape] ? "\\special{landscape}" : ""
|
68
|
+
puts "\\documentclass[#{@extras[:fontsize]}#{twocolumn}]{article}"
|
69
|
+
@usePackages.each{|package| puts "\\usepackage#{package}"}
|
70
|
+
puts "\\addtolength{\\oddsidemargin}{-3.5cm}"
|
71
|
+
puts "\\addtolength{\\textwidth}{7cm}"
|
72
|
+
puts "\\addtolength{\\topmargin}{-3cm}"
|
73
|
+
puts "\\addtolength{\\textheight}{5cm}"
|
74
|
+
puts "\\newcommand{\\hide}[1]{}"
|
75
|
+
puts "#{landscape}"
|
76
|
+
puts "\\begin{document}"
|
77
|
+
puts "\\DeclareGraphicsExtensions{.jpg,.pdf,.mps,.png}"
|
78
|
+
end
|
79
|
+
|
80
|
+
#Write the latex-file footer and closes the file.
|
81
|
+
def close
|
82
|
+
puts "\\end{document}"
|
83
|
+
super
|
84
|
+
end
|
85
|
+
|
86
|
+
#Prints a string to the latex file and indents each line with respect to the
|
87
|
+
#current indentation level that depends on nested blocks.
|
88
|
+
def puts(string)
|
89
|
+
lines = string.split("\n")
|
90
|
+
for line in lines
|
91
|
+
@indent -= 2 if line[0,5]=='\\end{' && @indent >= 2
|
92
|
+
if @lastWasPrint
|
93
|
+
super(line)
|
94
|
+
@lastWasPrint = false
|
95
|
+
else
|
96
|
+
super(" " * @indent + line)
|
97
|
+
end
|
98
|
+
@indent += 2 if line[0,7]=='\\begin{'
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
#Insert spaces up to the current indentation level
|
103
|
+
def indent
|
104
|
+
print " "*@indent
|
105
|
+
end
|
106
|
+
|
107
|
+
#Other than puts, print does NOT indent the text. If you want to do so
|
108
|
+
#call +indent+ before.
|
109
|
+
def print(string)
|
110
|
+
@lastWasPrint = true
|
111
|
+
@indent -= 2 if string[/\\end/]
|
112
|
+
@indent += 2 if string[/\\begin/]
|
113
|
+
super(string)
|
114
|
+
end
|
115
|
+
|
116
|
+
# Easy creation of environments.
|
117
|
+
# +name+:: the name of the environment.
|
118
|
+
# +args+:: an optional list of arguments that will be added after the environment definition.
|
119
|
+
# === Example:
|
120
|
+
# tex.env("table","[ht]") do
|
121
|
+
# tex.puts "<table body>"
|
122
|
+
# end
|
123
|
+
def env(name, *args)
|
124
|
+
puts "\\begin{#{name}}#{args}"
|
125
|
+
yield if block_given?
|
126
|
+
puts "\\end{#{name}}"
|
127
|
+
end
|
128
|
+
|
129
|
+
########### Figure generation #################################################
|
130
|
+
|
131
|
+
#Inserts one (ore more) figure block(s) with given figures as subfigures.
|
132
|
+
#+figures+::
|
133
|
+
# is an array consisting of +Figure+ instances.
|
134
|
+
# <tt>Figure = Struct.new(:format, :filename, :title)</tt>
|
135
|
+
# If +format+ begins with a number, it is assumed to be the width of the image.
|
136
|
+
# But you can also set e.g. <tt>"height=10.5cm,angle=-90"</tt>.
|
137
|
+
# For more info see the documentation to <tt>\includegraphics </tt> in the
|
138
|
+
# +graphicx+ package of _LaTeX_.
|
139
|
+
#+caption+:: is placed on each figure block that is created.
|
140
|
+
#+newPageThreshold+::
|
141
|
+
# is maximum the number of figures in a block.
|
142
|
+
# If more figures are given then a new block is created with the same
|
143
|
+
# caption.
|
144
|
+
#+placement+:: an optional placement for the figure blocks.
|
145
|
+
#+label+:: an optional label of the figures block ('fig:' is added)
|
146
|
+
# You can also use label="\\hypertarget{...}" if you like.
|
147
|
+
# Otherwise a \label{fig:...} is generated.
|
148
|
+
#=== Example:
|
149
|
+
# Experiment = Struct.new(:caption, :figures)
|
150
|
+
# thisExperiment = Experiment.new
|
151
|
+
# thisExperiment.caption = "Instance: #{instance}_1.dat".escape_
|
152
|
+
# thisExperiment.figures = [
|
153
|
+
# Figure.new("6.5cm", epsDirectory, "#{instance}-a.eps"),
|
154
|
+
# Figure.new("6.5cm", epsDirectory, "#{instance}-b.eps"),
|
155
|
+
# Figure.new("14cm", epsDirectory, "#{instance}-c.eps", "Title for image c)")
|
156
|
+
# ]
|
157
|
+
# tex.figures(thisExperiment.caption, thisExperiment.figures, 3)
|
158
|
+
def figures(caption, figures, newPageThreshold, placement = "htbp", label = nil)
|
159
|
+
lastimagepath = ""
|
160
|
+
figures.each_with_index do |figure,i|
|
161
|
+
figure.title = "[{#{figure.title}}]" unless figure.title == "" or figure.title == nil
|
162
|
+
if i % newPageThreshold == 0
|
163
|
+
puts "\\begin{figure}[#{placement}]"
|
164
|
+
puts "\\caption{#{caption}}"
|
165
|
+
if label
|
166
|
+
if label[0,1]=='\\' #you can use \hypertarget here
|
167
|
+
puts label
|
168
|
+
else
|
169
|
+
puts "\\label{fig:#{label}}"
|
170
|
+
end
|
171
|
+
end
|
172
|
+
puts "\\centering"
|
173
|
+
end
|
174
|
+
imagepath = File.dirname(figure.filename)
|
175
|
+
puts "\\graphicspath{{#{imagepath}}}" if imagepath != "" and imagepath != "." and lastimagepath != imagepath
|
176
|
+
lastimagepath = imagepath
|
177
|
+
figure.format = "width="+figure.format if figure.format =~ /^[0-9\.]/
|
178
|
+
if figure.label
|
179
|
+
if figure.label[0,1]=='\\'
|
180
|
+
puts figure.label
|
181
|
+
else
|
182
|
+
puts "\\label{#{figure.label}}"
|
183
|
+
end
|
184
|
+
end
|
185
|
+
puts "\\subfigure#{figure.title}{\\includegraphics[#{figure.format}]{#{File.basename(figure.filename)}}}"
|
186
|
+
if i % newPageThreshold == newPageThreshold-1 or figure == figures[-1]
|
187
|
+
puts "\\end{figure}"
|
188
|
+
puts "\\clearpage"
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
########### Table Generation functions #################################################
|
194
|
+
|
195
|
+
#This is a helper function for table generation.
|
196
|
+
#It computes the number of columns that are leaves of the tree with root +header_node+.
|
197
|
+
#You can also say, it computes the number of leaves of the given tree.
|
198
|
+
#+header+:: is of type +Header+: (name, children)
|
199
|
+
def getNumColsOfHeader(header)
|
200
|
+
header.children.inject(0) do |numChildren, child|
|
201
|
+
numChildren + (child.children ? getNumColsOfHeader(child) : 1)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
private :getNumColsOfHeader
|
205
|
+
|
206
|
+
#+list+:: must contain hashes as values for all keys.
|
207
|
+
#These child hashes will be joined/merged to one big hash.
|
208
|
+
#The actual leafes will be ignored so that only the header remain.
|
209
|
+
def getHeaderMergedHash(list)
|
210
|
+
merged = {}
|
211
|
+
toMerge = Hash.new {|h,k| h[k] = [] }
|
212
|
+
nothingToMerge = true
|
213
|
+
for entry in list
|
214
|
+
if entry.class == Hash
|
215
|
+
entry.each_pair do |key,value|
|
216
|
+
toMerge[key] << value
|
217
|
+
end
|
218
|
+
nothingToMerge = false
|
219
|
+
end
|
220
|
+
end
|
221
|
+
#return list if nothingToMerge
|
222
|
+
return nil if nothingToMerge #return only header tree without any data
|
223
|
+
toMerge.each_pair do |key,value|
|
224
|
+
if key.class == Symbol
|
225
|
+
merged[key] = value unless merged[key]
|
226
|
+
else
|
227
|
+
merged[key] = getHeaderMergedHash(value)
|
228
|
+
end
|
229
|
+
end
|
230
|
+
return merged
|
231
|
+
end
|
232
|
+
private :getHeaderMergedHash
|
233
|
+
|
234
|
+
@@default_sort = Proc.new { |x,y| x <=> y }
|
235
|
+
|
236
|
+
#Given a list of hashes, initially a hash-list of each row it
|
237
|
+
#returns a sorted tree representation - a headerList.
|
238
|
+
#+sort_block+:: a block that compares header names
|
239
|
+
#side effects::
|
240
|
+
# deletes :align entries from the +hash+ and transforms
|
241
|
+
# hash[:value] = value hashes to normal entries
|
242
|
+
def hash2HeaderList(hash, sort_block = @@default_sort)
|
243
|
+
headerList = []
|
244
|
+
entries = hash.to_a
|
245
|
+
entries.sort! do |x,y| sort_block.call(x[0],y[0])
|
246
|
+
end
|
247
|
+
for key,value in entries
|
248
|
+
if value.class == Hash
|
249
|
+
align = value.delete(:align) || @default_table_align
|
250
|
+
align = align[0] if align.class == Array
|
251
|
+
if value[:value] #transform hashes with :value keys to normal entries
|
252
|
+
hash[key] = value = value[:value]
|
253
|
+
headerList << Header.new(key,align,nil)
|
254
|
+
else
|
255
|
+
subtree = hash2HeaderList(value, sort_block)
|
256
|
+
headerList << Header.new(key,align,subtree)
|
257
|
+
end
|
258
|
+
else
|
259
|
+
headerList << Header.new(key,@default_table_align,nil)
|
260
|
+
end
|
261
|
+
end
|
262
|
+
return headerList
|
263
|
+
end
|
264
|
+
private :hash2HeaderList
|
265
|
+
|
266
|
+
#Performes a breath first traversal of the given tree
|
267
|
+
#+headerList+:: a list of header nodes of class +Header+.
|
268
|
+
#Returns a list of headers (together with the number of columns they use) for each header line needed.
|
269
|
+
#example: <tt>[['B',['C',['F','G']], ['D',['H','I']],['E']]]</tt> =>
|
270
|
+
#<tt>[['B'], ['C','D','E'], ['F','G','H','I']]</tt> and with their column width information
|
271
|
+
#if the (sub)header covers more than one column =>
|
272
|
+
#<tt>[[['B',5]], [['C',2],['D',2],'E'], ['F','G','H','I']]</tt>
|
273
|
+
#The length of the returned list is the number of rows needed for the headers.
|
274
|
+
def getHeaderLines(headerList) #:nodoc:
|
275
|
+
line = []
|
276
|
+
nextLevel = [] # collects the children nodes of all nodes processed (BFS)
|
277
|
+
hasChildrenInNextLevel = false
|
278
|
+
for header in headerList
|
279
|
+
if header.is_a?(Array) and header[0] == "~"
|
280
|
+
line << header
|
281
|
+
nextLevel << header # insert this for lines below this
|
282
|
+
elsif header.children == nil # leaf node ?
|
283
|
+
line << [header.name, header.align]
|
284
|
+
nextLevel << ["~",header.align] # insert this for lines below this
|
285
|
+
else
|
286
|
+
line << [header.name, header.align, getNumColsOfHeader(header)]
|
287
|
+
nextLevel += header.children
|
288
|
+
hasChildrenInNextLevel = true
|
289
|
+
end
|
290
|
+
end
|
291
|
+
return hasChildrenInNextLevel ? [line] + getHeaderLines(nextLevel) : [line]
|
292
|
+
end
|
293
|
+
private :getHeaderLines
|
294
|
+
|
295
|
+
#Returns a list of paths to all leaf nodes of the given header-tree list. The Leaf nodes are the final
|
296
|
+
#columns. In order to compute the table value at (row,col) we want to access only the leaf cols and not
|
297
|
+
#the header columns.
|
298
|
+
#Example: let <tt>[['B',['C',['F','G']], ['D',['H','I']],['E']]]</tt> be our
|
299
|
+
#header tree. The real columns are F,G,H,I,E. In order to access e.g. 'I' we need to know the path [B,D,I].
|
300
|
+
#<tt> => [["B", "C", "F"], ["B", "C", "G"], ["B", "D", "H"], ["B", "D", "I"], ["B", "E"]]</tt>
|
301
|
+
def getLeafColumns(headerList, path_prefix = nil) #:nodoc:
|
302
|
+
paths = []
|
303
|
+
path_prefix = path_prefix || []
|
304
|
+
for header in headerList
|
305
|
+
if header.children
|
306
|
+
paths += getLeafColumns(header.children, path_prefix + [header.name])
|
307
|
+
else #header is not of class Header but a leaf header (string)
|
308
|
+
paths << path_prefix + [header.name]
|
309
|
+
end
|
310
|
+
end
|
311
|
+
return paths
|
312
|
+
end
|
313
|
+
private :getLeafColumns
|
314
|
+
|
315
|
+
#Pretty print output of table entries. If an entry is an array then
|
316
|
+
#+prettyPrintCell+ will be called for every table item. You can override this
|
317
|
+
#function if you like a special behaviour.
|
318
|
+
def prettyPrintCell(x)
|
319
|
+
if x.kind_of?(Integer)
|
320
|
+
x = "%d" % x
|
321
|
+
elsif x.kind_of?(Float)
|
322
|
+
x = "%.2f" % x
|
323
|
+
else
|
324
|
+
x = x.to_s
|
325
|
+
end
|
326
|
+
raise(FormatError, "Invalid format: #{x.inspect} contains % that is not sufficiently quoted for latex.", caller) if x =~ /[^\\]%|^%/
|
327
|
+
x.gsub(/1.#J|Infinity|1.#INF0/, "$\\infty$")
|
328
|
+
end
|
329
|
+
|
330
|
+
|
331
|
+
# Generates a table with the specified entries.
|
332
|
+
# +entries+::
|
333
|
+
# the row-hash where the keys are the row names which are printed in the first column.
|
334
|
+
# The <tt>entries[row]</tt> is a column-hash. Its keys are the column names.
|
335
|
+
# A column-hash value can be either
|
336
|
+
# - an object (with a <tt>to_s</tt> method) that are printed
|
337
|
+
# - an array containing objects. In this case a new row is added for each array entry
|
338
|
+
# - a hash in which case the keys of this hash are subheaders.
|
339
|
+
# +caption+:: the caption of the table.
|
340
|
+
# +args+::
|
341
|
+
# is either a hash or further arguments
|
342
|
+
# Case 1::
|
343
|
+
# The hash is indexed by one of the argument symbols below, the values correspond to the
|
344
|
+
# argument values you want to set to the corresponding argument.
|
345
|
+
# Instead of symbols you can also use strings, e.g. <tt>:label</tt> or <tt>"label"<</tt>
|
346
|
+
# Case 2::
|
347
|
+
# args are some more arguments. Then they will be interpreted as the following arguments
|
348
|
+
# in the same order. You need not use all of them.
|
349
|
+
# <tt>:rowTitle</tt>:: the title of the first column that contains the row names.
|
350
|
+
# <tt>:label</tt>:: the label of the table. The "tab:" prefix is added automatically .
|
351
|
+
# <tt>:newTableThreshold</tt>::
|
352
|
+
# maximum number of lines per table. If reached then a new table will be created.
|
353
|
+
# Zero means no restriction. An empty row (entries[name] == nil) also toggles a new table.
|
354
|
+
# <tt>:placement</tt>:: the LaTeX placement for the table. See the LaTeX documentation for details.
|
355
|
+
# <tt>:empty</tt>:: a string that will be put in those fields that have no value.
|
356
|
+
# <tt>:sort</tt>::
|
357
|
+
# is used to sort the rows and columns. Default is alphabetical ordering.
|
358
|
+
# See the example below to get an idea on how to implement customized ordering.
|
359
|
+
# <tt>:landscape</tt>:: if true, it will turn the page by 90 degree.
|
360
|
+
# <tt>:fontSize</tt>::
|
361
|
+
# A latex fontsize modifier like tiny, scriptsize, footnotesize, small,
|
362
|
+
# normalsize (default), large, Large, LARGE, huge, Huge.
|
363
|
+
# <tt>:header_hlines</tt>::
|
364
|
+
# If +true+, then horizontal lines between headers of different depths are drawn.
|
365
|
+
# Default is +false+ (no horizontal header lines).
|
366
|
+
# <tt>:rowAlign</tt>::
|
367
|
+
# Alignment of the column containing the row names. Values are 'r','c','l'.
|
368
|
+
# See also the attribute +default_table_align+.
|
369
|
+
#
|
370
|
+
# === Example:
|
371
|
+
# require 'latex'
|
372
|
+
# tex = LatexFile.new("table.tex")
|
373
|
+
# rows["row1"] = {'Main Header'=>
|
374
|
+
# {'A'=> '5',
|
375
|
+
# 'B'=> {'D'=>'1','E'=>'2'},
|
376
|
+
# 'C'=> {'F'=>'3','G'=>'4'}},
|
377
|
+
# 'X'=> [1,3,55.55]}
|
378
|
+
# tex.table(rows,"table with hierarchical headers",:rowTitle=>"Instance")
|
379
|
+
# tableSort = Proc.new do |x,y|
|
380
|
+
# order = %w{A X B C D E}
|
381
|
+
# (order.index(x) && order.index(y)) ? order.index(x) <=> order.index(y) : x <=> y
|
382
|
+
# end
|
383
|
+
# tex.table(rows,"special ordering", :rowTitle=>"Instance", :sort => tableSort)
|
384
|
+
#
|
385
|
+
# === Column alignment:
|
386
|
+
# By default alignment is centered. You can change this for all columns using the attribute
|
387
|
+
# +default_table_align+.
|
388
|
+
# The alignment can also be changed for each column separately:
|
389
|
+
# Headers can be aligned as demonstrated in the following examples:
|
390
|
+
# rows['1'] = {'Main Header' => {:align => 'l', 'A' => '5','B' => '6'}}
|
391
|
+
# This affects only the header and not the columns, because this is no final column header.
|
392
|
+
# Subheader and so the final columns themselves are aligned as follows:
|
393
|
+
# rows['1'] = {'Main Header' => {'A' => {:value => '5', :align => 'l'} ,'B' => '6'}}
|
394
|
+
# rows['2'] = {'Main Header' => {'A' => '77','B' => '8'}}
|
395
|
+
# As you can see it is only needed to define the alignment of a column once. It can be done
|
396
|
+
# as often as you like but only one alignment definition is used.
|
397
|
+
def table(entries, caption, *args)
|
398
|
+
tableValidArgs = [:rowTitle, :label, :newTableThreshold, :placement, :empty, :sort, :landscape, :fontSize, :grouping, :header_hlines, :rowAlign]
|
399
|
+
# raise(ArgumentError,"Too many arguments Latex.table", caller) unless args.length <= 1
|
400
|
+
hash = {}
|
401
|
+
args = if args[0].kind_of?(Hash)
|
402
|
+
args[0].each_pair{|key,value| hash[key.to_sym]= value}; hash # allow string keys also
|
403
|
+
else
|
404
|
+
args.each_with_index{|arg,i| hash[tableValidArgs[i].to_sym] = arg}; hash
|
405
|
+
end
|
406
|
+
args.each_key{|key| raise(ArgumentError,"Invalid argument: #{key} for Latex.table", caller) unless tableValidArgs.include?(key)}
|
407
|
+
@tableCaption = caption
|
408
|
+
rowTitle = args[:rowTitle] || ""
|
409
|
+
@tableLabel = args[:label] || ""
|
410
|
+
newTableThreshold = args[:newTableThreshold] || (args[:landscape] ? 38 : 60)
|
411
|
+
placement = args[:placement] || "htbp"
|
412
|
+
empty = args[:empty] ||"-"
|
413
|
+
sort_block = args[:sort] ||@@default_sort
|
414
|
+
grouping = args[:grouping] || [entries.keys]
|
415
|
+
@tableLandscape = args[:landscape]
|
416
|
+
@tableFontSize = args[:fontSize] || @defaultTableFontSize
|
417
|
+
@header_hlines = args[:header_hlines]
|
418
|
+
@rowAlign = args[:rowAlign] || @default_table_align
|
419
|
+
|
420
|
+
#access an element in the table which is located in row _rowName_ and in a column
|
421
|
+
#that is defined by a _path_ through the headers that can be obtained with
|
422
|
+
#the function +getLeafColumns+.
|
423
|
+
def accessElement(entries, rowName, path) #:nodoc:
|
424
|
+
entry = entries[rowName]
|
425
|
+
for key in path
|
426
|
+
entry = entry[key]
|
427
|
+
return [] unless entry
|
428
|
+
end
|
429
|
+
entry = entry[:value] if entry.is_a?(Hash)
|
430
|
+
return entry.is_a?(Array) ? entry : [entry]
|
431
|
+
end
|
432
|
+
|
433
|
+
def printTableHeader(placement, headerLines, leafColumns, rowTitle) #:nodoc:
|
434
|
+
puts "\\begin{landscape}" if @tableLandscape
|
435
|
+
puts "\n\\begin{table}[#{placement}]\n\\begin{center}"
|
436
|
+
puts "\\#{@tableFontSize}" if @tableFontSize
|
437
|
+
print " "*@indent + "\\begin{tabular}{|"
|
438
|
+
# print the alignment {c,r,l} for each leaf column
|
439
|
+
print "#{@rowAlign}|" # the first column with the row names
|
440
|
+
headerLines[-1].each {|headerName, colAlign| print "#{colAlign}|" }
|
441
|
+
puts "}"
|
442
|
+
currentHeaderRowNumber = 0
|
443
|
+
puts "\\hline"
|
444
|
+
for headerLine in headerLines
|
445
|
+
print " "*@indent
|
446
|
+
if headerLine == headerLines[-1]
|
447
|
+
print "#{rowTitle} & " # row name title comes in the last header line
|
448
|
+
else
|
449
|
+
print "~ & "
|
450
|
+
end
|
451
|
+
currentColumn = 2
|
452
|
+
cline = ""
|
453
|
+
print headerLine.map {|headerName, align, columns|
|
454
|
+
raise(FormatError, "Invalid format: #{headerName.inspect} contains % that is not sufficiently quoted for latex.", caller) if headerName =~ /[^\\]%|^%/
|
455
|
+
if columns
|
456
|
+
cline += "\\cline{#{currentColumn}-#{(currentColumn+=columns)-1}}" if @header_hlines
|
457
|
+
"\\multicolumn{#{columns}}{#{align}|}{#{headerName}}"
|
458
|
+
else
|
459
|
+
currentColumn += 1
|
460
|
+
if currentHeaderRowNumber == headerLines.length-1 || headerName == "~"
|
461
|
+
headerName
|
462
|
+
else
|
463
|
+
delta = "%.1f" % ((headerLines.length-currentHeaderRowNumber-1).to_f)
|
464
|
+
"\\raisebox{-#{delta}\\totalheight}[1ex][1ex]{#{headerName}}"
|
465
|
+
end
|
466
|
+
end
|
467
|
+
}.join(" & ")
|
468
|
+
puts "\\\\"+cline
|
469
|
+
currentHeaderRowNumber += 1
|
470
|
+
end
|
471
|
+
puts "\\hline\\hline"
|
472
|
+
end
|
473
|
+
|
474
|
+
def printTableFooter #:nodoc:
|
475
|
+
puts "\\end{tabular}"
|
476
|
+
puts "\\caption{#{@tableCaption}}\n\\label{tab:#@tableLabel}"
|
477
|
+
puts "\\end{center}\n\\end{table}\n"
|
478
|
+
puts "\\end{landscape}" if @tableLandscape
|
479
|
+
end
|
480
|
+
|
481
|
+
#====== Generate header
|
482
|
+
headerList = hash2HeaderList(getHeaderMergedHash(entries.values), sort_block)
|
483
|
+
headerLines = getHeaderLines(headerList)
|
484
|
+
leafColumns = getLeafColumns(headerList)
|
485
|
+
printTableHeader(placement, headerLines, leafColumns, rowTitle)
|
486
|
+
|
487
|
+
currentRow = 0
|
488
|
+
for row_names in grouping
|
489
|
+
#======= Compute table break for multiple groupings.
|
490
|
+
new_lines = 0
|
491
|
+
for row_name in row_names
|
492
|
+
max_lines_per_entry = 1
|
493
|
+
for col_header in leafColumns
|
494
|
+
max_lines_per_entry = [max_lines_per_entry, accessElement(entries,row_name,col_header).length].max
|
495
|
+
end
|
496
|
+
new_lines += max_lines_per_entry
|
497
|
+
end
|
498
|
+
|
499
|
+
if (currentRow > 0 and currentRow + new_lines >= newTableThreshold)
|
500
|
+
currentRow = 0
|
501
|
+
printTableFooter # close last table
|
502
|
+
printTableHeader(placement, headerLines, leafColumns, rowTitle) # open new table
|
503
|
+
else
|
504
|
+
unless currentRow == 0
|
505
|
+
puts "\\hline" unless row_names == []
|
506
|
+
currentRow += 0.5
|
507
|
+
end
|
508
|
+
end
|
509
|
+
|
510
|
+
row_names.sort! &sort_block
|
511
|
+
#====== Generate entries.
|
512
|
+
for row_name in row_names
|
513
|
+
if (newTableThreshold > 0 and currentRow >= newTableThreshold)
|
514
|
+
currentRow = 0
|
515
|
+
printTableFooter # close last table
|
516
|
+
printTableHeader(placement, headerLines, leafColumns, rowTitle) # open new table
|
517
|
+
end
|
518
|
+
max_lines_per_entry = 1
|
519
|
+
for col_header in leafColumns
|
520
|
+
max_lines_per_entry = [max_lines_per_entry, accessElement(entries,row_name,col_header).length].max
|
521
|
+
end
|
522
|
+
|
523
|
+
for i in 0...max_lines_per_entry
|
524
|
+
#print row-name
|
525
|
+
print " "*@indent
|
526
|
+
output = (i==0 ? row_name.to_s.gsub(/_/,"\\_") : "~")
|
527
|
+
delta = "%.1f" % ((max_lines_per_entry-1).to_f)
|
528
|
+
output = "\\raisebox{-#{delta}\\totalheight}[1ex][1ex]{#{output}}" if max_lines_per_entry > 1
|
529
|
+
print output
|
530
|
+
|
531
|
+
#print the other columns
|
532
|
+
for col_header in leafColumns
|
533
|
+
entry = accessElement(entries,row_name,col_header)
|
534
|
+
if entry[i]
|
535
|
+
output = prettyPrintCell(entry[i])
|
536
|
+
delta = "%.1f" % (max_lines_per_entry-entry.length).to_f
|
537
|
+
else
|
538
|
+
output = (i==0 ? empty : "~")
|
539
|
+
delta = max_lines_per_entry
|
540
|
+
end
|
541
|
+
#Center the entries vertically in the cell. Out-comment this if you don't like that.
|
542
|
+
if entry.length != max_lines_per_entry# && entry.length > 0
|
543
|
+
output = "\\raisebox{-#{delta}\\totalheight}[1ex][1ex]{#{output}}" unless output == "~"
|
544
|
+
end
|
545
|
+
print " & " + output
|
546
|
+
end
|
547
|
+
puts "\\\\"
|
548
|
+
end
|
549
|
+
puts "\\hline"
|
550
|
+
currentRow += max_lines_per_entry
|
551
|
+
end
|
552
|
+
end
|
553
|
+
#====== Generate footer.
|
554
|
+
printTableFooter
|
555
|
+
end
|
556
|
+
end
|
557
|
+
|
558
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
\relax
|
2
|
+
\ifx\hyper@anchor\@undefined
|
3
|
+
\global \let \oldcontentsline\contentsline
|
4
|
+
\gdef \contentsline#1#2#3#4{\oldcontentsline{#1}{#2}{#3}}
|
5
|
+
\global \let \oldnewlabel\newlabel
|
6
|
+
\gdef \newlabel#1#2{\newlabelxx{#1}#2}
|
7
|
+
\gdef \newlabelxx#1#2#3#4#5#6{\oldnewlabel{#1}{{#2}{#3}}}
|
8
|
+
\AtEndDocument{\let \contentsline\oldcontentsline
|
9
|
+
\let \newlabel\oldnewlabel}
|
10
|
+
\else
|
11
|
+
\global \let \hyper@last\relax
|
12
|
+
\fi
|
13
|
+
|
14
|
+
\@writefile{lot}{\contentsline {table}{\numberline {1}{\ignorespaces common table}}{1}{table.1}}
|
15
|
+
\newlabel{tab:}{{1}{1}{\relax }{table.1}{}}
|
16
|
+
\@writefile{lot}{\contentsline {table}{\numberline {2}{\ignorespaces hierarchical headers}}{1}{table.2}}
|
17
|
+
\newlabel{tab:}{{2}{1}{\relax }{table.2}{}}
|
18
|
+
\@writefile{lot}{\contentsline {table}{\numberline {3}{\ignorespaces both tables}}{2}{table.3}}
|
19
|
+
\newlabel{tab:}{{3}{2}{\relax }{table.3}{}}
|
Binary file
|
@@ -0,0 +1,197 @@
|
|
1
|
+
This is TeXk, Version 3.14159 (Web2C 7.4.5) (format=latex 2003.11.5) 12 OCT 2004 15:46
|
2
|
+
Source specials enabled.
|
3
|
+
**\nonstopmode\input{latextest.tex}
|
4
|
+
(./latextest.tex (/usr/share/texmf/tex/latex/base/article.cls
|
5
|
+
Document Class: article 2001/04/21 v1.4e Standard LaTeX document class
|
6
|
+
(/usr/share/texmf/tex/latex/base/size10.clo
|
7
|
+
File: size10.clo 2001/04/21 v1.4e Standard LaTeX file (size option)
|
8
|
+
)
|
9
|
+
\c@part=\count79
|
10
|
+
\c@section=\count80
|
11
|
+
\c@subsection=\count81
|
12
|
+
\c@subsubsection=\count82
|
13
|
+
\c@paragraph=\count83
|
14
|
+
\c@subparagraph=\count84
|
15
|
+
\c@figure=\count85
|
16
|
+
\c@table=\count86
|
17
|
+
\abovecaptionskip=\skip41
|
18
|
+
\belowcaptionskip=\skip42
|
19
|
+
\bibindent=\dimen102
|
20
|
+
)
|
21
|
+
(/usr/share/texmf/tex/latex/base/inputenc.sty
|
22
|
+
Package: inputenc 2001/07/10 v0.99a Input encoding file
|
23
|
+
|
24
|
+
(/usr/share/texmf/tex/latex/base/latin1.def
|
25
|
+
File: latin1.def 2001/07/10 v0.99a Input encoding file
|
26
|
+
))
|
27
|
+
(/usr/share/texmf/tex/latex/graphics/graphics.sty
|
28
|
+
Package: graphics 2001/07/07 v1.0n Standard LaTeX Graphics (DPC,SPQR)
|
29
|
+
|
30
|
+
(/usr/share/texmf/tex/latex/graphics/trig.sty
|
31
|
+
Package: trig 1999/03/16 v1.09 sin cos tan (DPC)
|
32
|
+
)
|
33
|
+
(/usr/share/texmf/tex/latex/config/graphics.cfg
|
34
|
+
File: graphics.cfg 2001/08/31 v1.1 graphics configuration of teTeX/TeXLive
|
35
|
+
)
|
36
|
+
Package graphics Info: Driver file: dvips.def on input line 80.
|
37
|
+
|
38
|
+
(/usr/share/texmf/tex/latex/graphics/dvips.def
|
39
|
+
File: dvips.def 1999/02/16 v3.0i Driver-dependant file (DPC,SPQR)
|
40
|
+
))
|
41
|
+
(/usr/share/texmf/tex/latex/graphics/graphicx.sty
|
42
|
+
Package: graphicx 1999/02/16 v1.0f Enhanced LaTeX Graphics (DPC,SPQR)
|
43
|
+
|
44
|
+
(/usr/share/texmf/tex/latex/graphics/keyval.sty
|
45
|
+
Package: keyval 1999/03/16 v1.13 key=value parser (DPC)
|
46
|
+
\KV@toks@=\toks14
|
47
|
+
)
|
48
|
+
\Gin@req@height=\dimen103
|
49
|
+
\Gin@req@width=\dimen104
|
50
|
+
)
|
51
|
+
(/usr/share/texmf/tex/latex/graphics/color.sty
|
52
|
+
Package: color 1999/02/16 v1.0i Standard LaTeX Color (DPC)
|
53
|
+
|
54
|
+
(/usr/share/texmf/tex/latex/config/color.cfg
|
55
|
+
File: color.cfg 2001/08/31 v1.1 color configuration of teTeX/TeXLive
|
56
|
+
)
|
57
|
+
Package color Info: Driver file: dvips.def on input line 125.
|
58
|
+
|
59
|
+
(/usr/share/texmf/tex/latex/graphics/dvipsnam.def
|
60
|
+
File: dvipsnam.def 1999/02/16 v3.0i Driver-dependant file (DPC,SPQR)
|
61
|
+
))
|
62
|
+
(/usr/share/texmf/tex/latex/amsfonts/amsfonts.sty
|
63
|
+
Package: amsfonts 2001/10/25 v2.2f
|
64
|
+
\@emptytoks=\toks15
|
65
|
+
\symAMSa=\mathgroup4
|
66
|
+
\symAMSb=\mathgroup5
|
67
|
+
LaTeX Font Info: Overwriting math alphabet `\mathfrak' in version `bold'
|
68
|
+
(Font) U/euf/m/n --> U/euf/b/n on input line 132.
|
69
|
+
)
|
70
|
+
(/usr/share/texmf/tex/latex/misc/subfigure.sty
|
71
|
+
Package: subfigure 2002/07/30 v2.1.4 subfigure package
|
72
|
+
\subfigtopskip=\skip43
|
73
|
+
\subfigcapskip=\skip44
|
74
|
+
\subfigcaptopadj=\dimen105
|
75
|
+
\subfigbottomskip=\skip45
|
76
|
+
\subfigcapmargin=\dimen106
|
77
|
+
\subfiglabelskip=\skip46
|
78
|
+
\c@subfigure=\count87
|
79
|
+
\c@lofdepth=\count88
|
80
|
+
\c@subtable=\count89
|
81
|
+
\c@lotdepth=\count90
|
82
|
+
\subfig@top=\skip47
|
83
|
+
\subfig@bottom=\skip48
|
84
|
+
)
|
85
|
+
(/usr/share/texmf/tex/latex/graphics/lscape.sty
|
86
|
+
Package: lscape 2000/10/22 v3.01 Landscape Pages (DPC)
|
87
|
+
)
|
88
|
+
(/usr/share/texmf/tex/latex/hyperref/hyperref.sty
|
89
|
+
Package: hyperref 2003/01/22 v6.73n Hypertext links for LaTeX
|
90
|
+
\@linkdim=\dimen107
|
91
|
+
\Hy@linkcounter=\count91
|
92
|
+
\Hy@pagecounter=\count92
|
93
|
+
|
94
|
+
(/usr/share/texmf/tex/latex/hyperref/pd1enc.def
|
95
|
+
File: pd1enc.def 2003/01/22 v6.73n Hyperref: PDFDocEncoding definition (HO)
|
96
|
+
)
|
97
|
+
(/usr/share/texmf/tex/latex/config/hyperref.cfg
|
98
|
+
File: hyperref.cfg 2002/06/06 v1.2 hyperref configuration of TeXLive and teTeX
|
99
|
+
)
|
100
|
+
Package hyperref Info: Hyper figures OFF on input line 1792.
|
101
|
+
Package hyperref Info: Link nesting OFF on input line 1797.
|
102
|
+
Package hyperref Info: Hyper index ON on input line 1800.
|
103
|
+
Package hyperref Info: Plain pages ON on input line 1805.
|
104
|
+
Package hyperref Info: Backreferencing OFF on input line 1812.
|
105
|
+
|
106
|
+
Implicit mode ON; LaTeX internals redefined
|
107
|
+
Package hyperref Info: Bookmarks ON on input line 1916.
|
108
|
+
(/usr/share/texmf/tex/latex/html/url.sty
|
109
|
+
Package: url 1999/03/02 ver 1.4 Verb mode for urls, email addresses, and file
|
110
|
+
names
|
111
|
+
)
|
112
|
+
LaTeX Info: Redefining \url on input line 2055.
|
113
|
+
\Fld@menulength=\count93
|
114
|
+
\Field@Width=\dimen108
|
115
|
+
\Fld@charsize=\dimen109
|
116
|
+
\Choice@toks=\toks16
|
117
|
+
\Field@toks=\toks17
|
118
|
+
Package hyperref Info: Hyper figures OFF on input line 2513.
|
119
|
+
Package hyperref Info: Link nesting OFF on input line 2518.
|
120
|
+
Package hyperref Info: Hyper index ON on input line 2521.
|
121
|
+
Package hyperref Info: backreferencing OFF on input line 2528.
|
122
|
+
Package hyperref Info: Link coloring OFF on input line 2533.
|
123
|
+
\c@Item=\count94
|
124
|
+
\c@Hfootnote=\count95
|
125
|
+
)
|
126
|
+
*hyperref using default driver hdvips*
|
127
|
+
(/usr/share/texmf/tex/latex/hyperref/hdvips.def
|
128
|
+
File: hdvips.def 2003/01/22 v6.73n Hyperref driver for dvips
|
129
|
+
|
130
|
+
(/usr/share/texmf/tex/latex/hyperref/pdfmark.def
|
131
|
+
File: pdfmark.def 2003/01/22 v6.73n Hyperref definitions for pdfmark specials
|
132
|
+
\pdf@docset=\toks18
|
133
|
+
\pdf@box=\box26
|
134
|
+
\pdf@toks=\toks19
|
135
|
+
\pdf@defaulttoks=\toks20
|
136
|
+
\Fld@listcount=\count96
|
137
|
+
\@outlinefile=\write3
|
138
|
+
)) (./latextest.aux
|
139
|
+
|
140
|
+
LaTeX Warning: Label `tab:' multiply defined.
|
141
|
+
|
142
|
+
|
143
|
+
LaTeX Warning: Label `tab:' multiply defined.
|
144
|
+
|
145
|
+
)
|
146
|
+
\openout1 = `latextest.aux'.
|
147
|
+
|
148
|
+
LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 15.
|
149
|
+
LaTeX Font Info: ... okay on input line 15.
|
150
|
+
LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 15.
|
151
|
+
LaTeX Font Info: ... okay on input line 15.
|
152
|
+
LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 15.
|
153
|
+
LaTeX Font Info: ... okay on input line 15.
|
154
|
+
LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 15.
|
155
|
+
LaTeX Font Info: ... okay on input line 15.
|
156
|
+
LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 15.
|
157
|
+
LaTeX Font Info: ... okay on input line 15.
|
158
|
+
LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 15.
|
159
|
+
LaTeX Font Info: ... okay on input line 15.
|
160
|
+
LaTeX Font Info: Checking defaults for PD1/pdf/m/n on input line 15.
|
161
|
+
LaTeX Font Info: ... okay on input line 15.
|
162
|
+
Package hyperref Info: Link coloring OFF on input line 15.
|
163
|
+
(/usr/share/texmf/tex/latex/hyperref/nameref.sty
|
164
|
+
Package: nameref 2001/01/27 v2.19 Cross-referencing by name of section
|
165
|
+
\c@section@level=\count97
|
166
|
+
)
|
167
|
+
LaTeX Info: Redefining \ref on input line 15.
|
168
|
+
LaTeX Info: Redefining \pageref on input line 15.
|
169
|
+
(./latextest.out)
|
170
|
+
(./latextest.out)
|
171
|
+
\openout3 = `latextest.out'.
|
172
|
+
|
173
|
+
LaTeX Font Info: Try loading font information for U+msa on input line 20.
|
174
|
+
(/usr/share/texmf/tex/latex/amsfonts/umsa.fd
|
175
|
+
File: umsa.fd 2002/01/19 v2.2g AMS font definitions
|
176
|
+
)
|
177
|
+
LaTeX Font Info: Try loading font information for U+msb on input line 20.
|
178
|
+
|
179
|
+
(/usr/share/texmf/tex/latex/amsfonts/umsb.fd
|
180
|
+
File: umsb.fd 2002/01/19 v2.2g AMS font definitions
|
181
|
+
) [1
|
182
|
+
|
183
|
+
] [2] (./latextest.aux)
|
184
|
+
|
185
|
+
LaTeX Warning: There were multiply-defined labels.
|
186
|
+
|
187
|
+
)
|
188
|
+
Here is how much of TeX's memory you used:
|
189
|
+
2561 strings out of 95847
|
190
|
+
35076 string characters out of 1195962
|
191
|
+
105293 words of memory out of 1000001
|
192
|
+
5494 multiletter control sequences out of 10000+50000
|
193
|
+
5339 words of font info for 22 fonts, out of 500000 for 1000
|
194
|
+
14 hyphenation exceptions out of 1000
|
195
|
+
26i,9n,24p,689b,344s stack positions out of 1500i,500n,5000p,200000b,5000s
|
196
|
+
|
197
|
+
Output written on latextest.dvi (2 pages, 13996 bytes).
|
File without changes
|
@@ -0,0 +1,91 @@
|
|
1
|
+
\documentclass[10pt]{article}
|
2
|
+
\usepackage[latin1]{inputenc}
|
3
|
+
\usepackage[final]{graphics}
|
4
|
+
\usepackage[pdftex]{graphicx}
|
5
|
+
\usepackage[dvips]{color}
|
6
|
+
\usepackage{amsfonts}
|
7
|
+
\usepackage{subfigure}
|
8
|
+
\usepackage{lscape}
|
9
|
+
\usepackage{hyperref}
|
10
|
+
\addtolength{\oddsidemargin}{-3.5cm}
|
11
|
+
\addtolength{\textwidth}{7cm}
|
12
|
+
\addtolength{\topmargin}{-3cm}
|
13
|
+
\addtolength{\textheight}{5cm}
|
14
|
+
\newcommand{\hide}[1]{}
|
15
|
+
\begin{document}
|
16
|
+
\DeclareGraphicsExtensions{.jpg,.pdf,.mps,.png}
|
17
|
+
|
18
|
+
\begin{table}[htbp]
|
19
|
+
\begin{center}
|
20
|
+
\begin{tabular}{|c|c|c|c|c|}
|
21
|
+
\hline
|
22
|
+
& Col3 & col1 & col2 & col3\\
|
23
|
+
\hline\hline
|
24
|
+
\raisebox{-1.0\totalheight}[1ex][1ex]{row1} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-1.0\totalheight}[1ex][1ex]{r1c1} & \raisebox{-1.0\totalheight}[1ex][1ex]{r1c2} & r1c3\\
|
25
|
+
\raisebox{-1.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & 3\\
|
26
|
+
\hline
|
27
|
+
\raisebox{-2.0\totalheight}[1ex][1ex]{row2} & r2c3 & \raisebox{-2.0\totalheight}[1ex][1ex]{r2c1} & \raisebox{-2.0\totalheight}[1ex][1ex]{r2c2} & \raisebox{-3\totalheight}[1ex][1ex]{-}\\
|
28
|
+
\raisebox{-2.0\totalheight}[1ex][1ex]{~} & 1.4 & ~ & ~ & ~\\
|
29
|
+
\raisebox{-2.0\totalheight}[1ex][1ex]{~} & 2 & ~ & ~ & ~\\
|
30
|
+
\hline
|
31
|
+
\end{tabular}
|
32
|
+
\caption{common table}
|
33
|
+
\label{tab:}
|
34
|
+
\end{center}
|
35
|
+
\end{table}
|
36
|
+
|
37
|
+
\begin{table}[htbp]
|
38
|
+
\begin{center}
|
39
|
+
\begin{tabular}{|c|c|c|c|c|c|c|c|c|r|c|c|}
|
40
|
+
\hline
|
41
|
+
~ & \multicolumn{10}{l|}{B} & \raisebox{-3.0\totalheight}[1ex][1ex]{X}\\
|
42
|
+
~ & \raisebox{-2.0\totalheight}[1ex][1ex]{A} & \multicolumn{3}{c|}{C} & \multicolumn{4}{c|}{D} & \raisebox{-2.0\totalheight}[1ex][1ex]{E} & \raisebox{-2.0\totalheight}[1ex][1ex]{X} & ~\\
|
43
|
+
~ & ~ & \raisebox{-1.0\totalheight}[1ex][1ex]{F} & \raisebox{-1.0\totalheight}[1ex][1ex]{G} & \raisebox{-1.0\totalheight}[1ex][1ex]{G2} & \raisebox{-1.0\totalheight}[1ex][1ex]{H} & \raisebox{-1.0\totalheight}[1ex][1ex]{I} & \multicolumn{2}{c|}{I2} & ~ & ~ & ~\\
|
44
|
+
Rows & ~ & ~ & ~ & ~ & ~ & ~ & a & b & ~ & ~ & ~\\
|
45
|
+
\hline\hline
|
46
|
+
\raisebox{-2.0\totalheight}[1ex][1ex]{A1} & \raisebox{-1.0\totalheight}[1ex][1ex]{5} & \raisebox{-2.0\totalheight}[1ex][1ex]{1} & \raisebox{-2.0\totalheight}[1ex][1ex]{2} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-2.0\totalheight}[1ex][1ex]{3} & \raisebox{-2.0\totalheight}[1ex][1ex]{4} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-2.0\totalheight}[1ex][1ex]{11} & \raisebox{-3\totalheight}[1ex][1ex]{-} & 1\\
|
47
|
+
\raisebox{-2.0\totalheight}[1ex][1ex]{~} & \raisebox{-1.0\totalheight}[1ex][1ex]{6} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 3\\
|
48
|
+
\raisebox{-2.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 55.55\\
|
49
|
+
\hline
|
50
|
+
\raisebox{-3.0\totalheight}[1ex][1ex]{A2} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-3.0\totalheight}[1ex][1ex]{11} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-3.0\totalheight}[1ex][1ex]{22} & \raisebox{-3.0\totalheight}[1ex][1ex]{33} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-3.0\totalheight}[1ex][1ex]{44} & \raisebox{-3.0\totalheight}[1ex][1ex]{66} & \raisebox{-3.0\totalheight}[1ex][1ex]{55000} & 2.30 & \raisebox{-4\totalheight}[1ex][1ex]{-}\\
|
51
|
+
\raisebox{-3.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 5.11 & ~\\
|
52
|
+
\raisebox{-3.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 1 & ~\\
|
53
|
+
\raisebox{-3.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 4 & ~\\
|
54
|
+
\hline
|
55
|
+
\end{tabular}
|
56
|
+
\caption{hierarchical headers}
|
57
|
+
\label{tab:}
|
58
|
+
\end{center}
|
59
|
+
\end{table}
|
60
|
+
|
61
|
+
\begin{table}[htbp]
|
62
|
+
\begin{center}
|
63
|
+
\begin{tabular}{|c|c|c|c|c|c|c|c|c|r|c|c|c|c|c|c|}
|
64
|
+
\hline
|
65
|
+
~ & \multicolumn{10}{l|}{B} & \raisebox{-3.0\totalheight}[1ex][1ex]{Col3} & \raisebox{-3.0\totalheight}[1ex][1ex]{X} & \raisebox{-3.0\totalheight}[1ex][1ex]{col1} & \raisebox{-3.0\totalheight}[1ex][1ex]{col2} & \raisebox{-3.0\totalheight}[1ex][1ex]{col3}\\
|
66
|
+
~ & \raisebox{-2.0\totalheight}[1ex][1ex]{A} & \multicolumn{3}{c|}{C} & \multicolumn{4}{c|}{D} & \raisebox{-2.0\totalheight}[1ex][1ex]{E} & \raisebox{-2.0\totalheight}[1ex][1ex]{X} & ~ & ~ & ~ & ~ & ~\\
|
67
|
+
~ & ~ & \raisebox{-1.0\totalheight}[1ex][1ex]{F} & \raisebox{-1.0\totalheight}[1ex][1ex]{G} & \raisebox{-1.0\totalheight}[1ex][1ex]{G2} & \raisebox{-1.0\totalheight}[1ex][1ex]{H} & \raisebox{-1.0\totalheight}[1ex][1ex]{I} & \multicolumn{2}{c|}{I2} & ~ & ~ & ~ & ~ & ~ & ~ & ~\\
|
68
|
+
Instance & ~ & ~ & ~ & ~ & ~ & ~ & a & b & ~ & ~ & ~ & ~ & ~ & ~ & ~\\
|
69
|
+
\hline\hline
|
70
|
+
\raisebox{-2.0\totalheight}[1ex][1ex]{A1} & \raisebox{-1.0\totalheight}[1ex][1ex]{5} & \raisebox{-2.0\totalheight}[1ex][1ex]{1} & \raisebox{-2.0\totalheight}[1ex][1ex]{2} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-2.0\totalheight}[1ex][1ex]{3} & \raisebox{-2.0\totalheight}[1ex][1ex]{4} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-2.0\totalheight}[1ex][1ex]{11} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & 1 & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-}\\
|
71
|
+
\raisebox{-2.0\totalheight}[1ex][1ex]{~} & \raisebox{-1.0\totalheight}[1ex][1ex]{6} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 3 & ~ & ~ & ~\\
|
72
|
+
\raisebox{-2.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 55.55 & ~ & ~ & ~\\
|
73
|
+
\hline
|
74
|
+
\raisebox{-3.0\totalheight}[1ex][1ex]{A2} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-3.0\totalheight}[1ex][1ex]{11} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-3.0\totalheight}[1ex][1ex]{22} & \raisebox{-3.0\totalheight}[1ex][1ex]{33} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-3.0\totalheight}[1ex][1ex]{44} & \raisebox{-3.0\totalheight}[1ex][1ex]{66} & \raisebox{-3.0\totalheight}[1ex][1ex]{55000} & 2.30 & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-4\totalheight}[1ex][1ex]{-}\\
|
75
|
+
\raisebox{-3.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 5.11 & ~ & ~ & ~ & ~ & ~\\
|
76
|
+
\raisebox{-3.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 1 & ~ & ~ & ~ & ~ & ~\\
|
77
|
+
\raisebox{-3.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 4 & ~ & ~ & ~ & ~ & ~\\
|
78
|
+
\hline
|
79
|
+
\raisebox{-1.0\totalheight}[1ex][1ex]{row1} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-1.0\totalheight}[1ex][1ex]{r1c1} & \raisebox{-1.0\totalheight}[1ex][1ex]{r1c2} & r1c3\\
|
80
|
+
\raisebox{-1.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 3\\
|
81
|
+
\hline
|
82
|
+
\raisebox{-2.0\totalheight}[1ex][1ex]{row2} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & r2c3 & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-2.0\totalheight}[1ex][1ex]{r2c1} & \raisebox{-2.0\totalheight}[1ex][1ex]{r2c2} & \raisebox{-3\totalheight}[1ex][1ex]{-}\\
|
83
|
+
\raisebox{-2.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 1.4 & ~ & ~ & ~ & ~\\
|
84
|
+
\raisebox{-2.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 2 & ~ & ~ & ~ & ~\\
|
85
|
+
\hline
|
86
|
+
\end{tabular}
|
87
|
+
\caption{both tables}
|
88
|
+
\label{tab:}
|
89
|
+
\end{center}
|
90
|
+
\end{table}
|
91
|
+
\end{document}
|
@@ -0,0 +1,91 @@
|
|
1
|
+
\documentclass[]{article}
|
2
|
+
\usepackage[latin1]{inputenc}
|
3
|
+
\usepackage[final]{graphics}
|
4
|
+
\usepackage[pdftex]{graphicx}
|
5
|
+
\usepackage[dvips]{color}
|
6
|
+
\usepackage{amsfonts}
|
7
|
+
\usepackage{subfigure}
|
8
|
+
\usepackage{lscape}
|
9
|
+
\usepackage{hyperref}
|
10
|
+
\addtolength{\oddsidemargin}{-3.5cm}
|
11
|
+
\addtolength{\textwidth}{7cm}
|
12
|
+
\addtolength{\topmargin}{-3cm}
|
13
|
+
\addtolength{\textheight}{5cm}
|
14
|
+
\newcommand{\hide}[1]{}
|
15
|
+
\begin{document}
|
16
|
+
\DeclareGraphicsExtensions{.jpg,.pdf,.mps,.png}
|
17
|
+
|
18
|
+
\begin{table}[htbp]
|
19
|
+
\begin{center}
|
20
|
+
\begin{tabular}{|c|c|c|c|c|}
|
21
|
+
\hline
|
22
|
+
& Col3 & col1 & col2 & col3\\
|
23
|
+
\hline\hline
|
24
|
+
\raisebox{-1.0\totalheight}[1ex][1ex]{row1} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-1.0\totalheight}[1ex][1ex]{r1c1} & \raisebox{-1.0\totalheight}[1ex][1ex]{r1c2} & r1c3\\
|
25
|
+
\raisebox{-1.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & 3\\
|
26
|
+
\hline
|
27
|
+
\raisebox{-2.0\totalheight}[1ex][1ex]{row2} & r2c3 & \raisebox{-2.0\totalheight}[1ex][1ex]{r2c1} & \raisebox{-2.0\totalheight}[1ex][1ex]{r2c2} & \raisebox{-3\totalheight}[1ex][1ex]{-}\\
|
28
|
+
\raisebox{-2.0\totalheight}[1ex][1ex]{~} & 1.4 & ~ & ~ & ~\\
|
29
|
+
\raisebox{-2.0\totalheight}[1ex][1ex]{~} & 2 & ~ & ~ & ~\\
|
30
|
+
\hline
|
31
|
+
\end{tabular}
|
32
|
+
\caption{common table}
|
33
|
+
\label{tab:}
|
34
|
+
\end{center}
|
35
|
+
\end{table}
|
36
|
+
|
37
|
+
\begin{table}[htbp]
|
38
|
+
\begin{center}
|
39
|
+
\begin{tabular}{|c|c|c|c|c|c|c|c|c|r|c|c|}
|
40
|
+
\hline
|
41
|
+
~ & \multicolumn{10}{l|}{B} & \raisebox{-3.0\totalheight}[1ex][1ex]{X}\\
|
42
|
+
~ & \raisebox{-2.0\totalheight}[1ex][1ex]{A} & \multicolumn{3}{c|}{C} & \multicolumn{4}{c|}{D} & \raisebox{-2.0\totalheight}[1ex][1ex]{E} & \raisebox{-2.0\totalheight}[1ex][1ex]{X} & ~\\
|
43
|
+
~ & ~ & \raisebox{-1.0\totalheight}[1ex][1ex]{F} & \raisebox{-1.0\totalheight}[1ex][1ex]{G} & \raisebox{-1.0\totalheight}[1ex][1ex]{G2} & \raisebox{-1.0\totalheight}[1ex][1ex]{H} & \raisebox{-1.0\totalheight}[1ex][1ex]{I} & \multicolumn{2}{c|}{I2} & ~ & ~ & ~\\
|
44
|
+
Rows & ~ & ~ & ~ & ~ & ~ & ~ & a & b & ~ & ~ & ~\\
|
45
|
+
\hline\hline
|
46
|
+
\raisebox{-2.0\totalheight}[1ex][1ex]{A1} & \raisebox{-1.0\totalheight}[1ex][1ex]{5} & \raisebox{-2.0\totalheight}[1ex][1ex]{1} & \raisebox{-2.0\totalheight}[1ex][1ex]{2} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-2.0\totalheight}[1ex][1ex]{3} & \raisebox{-2.0\totalheight}[1ex][1ex]{4} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & 1\\
|
47
|
+
\raisebox{-2.0\totalheight}[1ex][1ex]{~} & \raisebox{-1.0\totalheight}[1ex][1ex]{6} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 3\\
|
48
|
+
\raisebox{-2.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 55.55\\
|
49
|
+
\hline
|
50
|
+
\raisebox{-3.0\totalheight}[1ex][1ex]{A2} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-3.0\totalheight}[1ex][1ex]{11} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-3.0\totalheight}[1ex][1ex]{22} & \raisebox{-3.0\totalheight}[1ex][1ex]{33} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-3.0\totalheight}[1ex][1ex]{44} & \raisebox{-3.0\totalheight}[1ex][1ex]{66} & \raisebox{-3.0\totalheight}[1ex][1ex]{55} & 2.30 & \raisebox{-4\totalheight}[1ex][1ex]{-}\\
|
51
|
+
\raisebox{-3.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 5.11 & ~\\
|
52
|
+
\raisebox{-3.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 1 & ~\\
|
53
|
+
\raisebox{-3.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 4 & ~\\
|
54
|
+
\hline
|
55
|
+
\end{tabular}
|
56
|
+
\caption{hierarchical headers}
|
57
|
+
\label{tab:}
|
58
|
+
\end{center}
|
59
|
+
\end{table}
|
60
|
+
|
61
|
+
\begin{table}[htbp]
|
62
|
+
\begin{center}
|
63
|
+
\begin{tabular}{|c|c|c|c|c|c|c|c|c|r|c|c|c|c|c|c|}
|
64
|
+
\hline
|
65
|
+
~ & \multicolumn{10}{l|}{B} & \raisebox{-3.0\totalheight}[1ex][1ex]{Col3} & \raisebox{-3.0\totalheight}[1ex][1ex]{X} & \raisebox{-3.0\totalheight}[1ex][1ex]{col1} & \raisebox{-3.0\totalheight}[1ex][1ex]{col2} & \raisebox{-3.0\totalheight}[1ex][1ex]{col3}\\
|
66
|
+
~ & \raisebox{-2.0\totalheight}[1ex][1ex]{A} & \multicolumn{3}{c|}{C} & \multicolumn{4}{c|}{D} & \raisebox{-2.0\totalheight}[1ex][1ex]{E} & \raisebox{-2.0\totalheight}[1ex][1ex]{X} & ~ & ~ & ~ & ~ & ~\\
|
67
|
+
~ & ~ & \raisebox{-1.0\totalheight}[1ex][1ex]{F} & \raisebox{-1.0\totalheight}[1ex][1ex]{G} & \raisebox{-1.0\totalheight}[1ex][1ex]{G2} & \raisebox{-1.0\totalheight}[1ex][1ex]{H} & \raisebox{-1.0\totalheight}[1ex][1ex]{I} & \multicolumn{2}{c|}{I2} & ~ & ~ & ~ & ~ & ~ & ~ & ~\\
|
68
|
+
Instance & ~ & ~ & ~ & ~ & ~ & ~ & a & b & ~ & ~ & ~ & ~ & ~ & ~ & ~\\
|
69
|
+
\hline\hline
|
70
|
+
\raisebox{-2.0\totalheight}[1ex][1ex]{A1} & \raisebox{-1.0\totalheight}[1ex][1ex]{5} & \raisebox{-2.0\totalheight}[1ex][1ex]{1} & \raisebox{-2.0\totalheight}[1ex][1ex]{2} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-2.0\totalheight}[1ex][1ex]{3} & \raisebox{-2.0\totalheight}[1ex][1ex]{4} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & 1 & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-}\\
|
71
|
+
\raisebox{-2.0\totalheight}[1ex][1ex]{~} & \raisebox{-1.0\totalheight}[1ex][1ex]{6} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 3 & ~ & ~ & ~\\
|
72
|
+
\raisebox{-2.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 55.55 & ~ & ~ & ~\\
|
73
|
+
\hline
|
74
|
+
\raisebox{-3.0\totalheight}[1ex][1ex]{A2} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-3.0\totalheight}[1ex][1ex]{11} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-3.0\totalheight}[1ex][1ex]{22} & \raisebox{-3.0\totalheight}[1ex][1ex]{33} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-3.0\totalheight}[1ex][1ex]{44} & \raisebox{-3.0\totalheight}[1ex][1ex]{66} & \raisebox{-3.0\totalheight}[1ex][1ex]{55} & 2.30 & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-4\totalheight}[1ex][1ex]{-}\\
|
75
|
+
\raisebox{-3.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 5.11 & ~ & ~ & ~ & ~ & ~\\
|
76
|
+
\raisebox{-3.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 1 & ~ & ~ & ~ & ~ & ~\\
|
77
|
+
\raisebox{-3.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 4 & ~ & ~ & ~ & ~ & ~\\
|
78
|
+
\hline
|
79
|
+
\raisebox{-1.0\totalheight}[1ex][1ex]{row1} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-1.0\totalheight}[1ex][1ex]{r1c1} & \raisebox{-1.0\totalheight}[1ex][1ex]{r1c2} & r1c3\\
|
80
|
+
\raisebox{-1.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 3\\
|
81
|
+
\hline
|
82
|
+
\raisebox{-2.0\totalheight}[1ex][1ex]{row2} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & r2c3 & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-2.0\totalheight}[1ex][1ex]{r2c1} & \raisebox{-2.0\totalheight}[1ex][1ex]{r2c2} & \raisebox{-3\totalheight}[1ex][1ex]{-}\\
|
83
|
+
\raisebox{-2.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 1.4 & ~ & ~ & ~ & ~\\
|
84
|
+
\raisebox{-2.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 2 & ~ & ~ & ~ & ~\\
|
85
|
+
\hline
|
86
|
+
\end{tabular}
|
87
|
+
\caption{both tables}
|
88
|
+
\label{tab:}
|
89
|
+
\end{center}
|
90
|
+
\end{table}
|
91
|
+
\end{document}
|
@@ -0,0 +1 @@
|
|
1
|
+
{" row1{" col1" r1c1" col2" r1c2" col3[" r1c3"3" row2{" col1" r2c1" col2" r2c2" Col3[" r2c3"1.4"2
|
data/examples/test-latex.rb
CHANGED
@@ -14,20 +14,24 @@ rows = {}
|
|
14
14
|
rows["A1"] = {'B'=>
|
15
15
|
{'A'=> ['5',6],
|
16
16
|
'C'=> {'F'=>'1','G'=>'2'},
|
17
|
-
'D'=> {'H'=>'3','I'=>'4'}
|
17
|
+
'D'=> {'H'=>'3','I'=>'4'},
|
18
|
+
'E'=> 11
|
18
19
|
},
|
19
20
|
'X'=>[1,3,55.55]}
|
20
|
-
rows["A2"] = {'B'=>
|
21
|
-
{
|
21
|
+
rows["A2"] = {'B'=>
|
22
|
+
{:align => "l", # define special alignment for the 'B' header, doesn't affect the final columns.
|
23
|
+
'C'=> {'F'=>'11','G2'=>'22'},
|
22
24
|
'D'=> {'H'=>'33','I2'=>{'a'=>'44','b'=>'66'}},
|
23
|
-
'E'=> '
|
24
|
-
'X'=>[2.3,5.111,1,4]}
|
25
|
+
'E'=> {:value => '55000', :align => 'r'}, # define alignment for the 'E' column and all data.
|
26
|
+
'X'=>[2.3,5.111,1,4]}}
|
27
|
+
|
25
28
|
tex.table(rows,"hierarchical headers", "Rows")
|
26
29
|
|
27
30
|
File.open("saved_table.dat","r") do |f|
|
28
31
|
old_rows = Marshal::load(f)
|
29
32
|
rows.merge!(old_rows)
|
30
33
|
end
|
34
|
+
|
31
35
|
tex.table(rows,"both tables",:rowTitle=>"Instance") do |x,y|
|
32
36
|
order = %w{X B C D E G F H col1 col2 col3 Col3}
|
33
37
|
if order.index(x) && order.index(y)
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'latex'
|
2
|
+
|
3
|
+
tex=LatexFile.new("latextest.tex")
|
4
|
+
rows = {}
|
5
|
+
rows["row1"] = {"col1" => "r1c1", "col2"=>"r1c2", "col3"=>["r1c3","3"]}
|
6
|
+
rows["row2"] = {"col1" => "r2c1", "col2"=>"r2c2", "Col3"=>["r2c3","1.4","2"]}
|
7
|
+
tex.table(rows,"common table")
|
8
|
+
|
9
|
+
File.open("saved_table.dat","w") do |f|
|
10
|
+
Marshal::dump(rows, f)
|
11
|
+
end
|
12
|
+
|
13
|
+
rows = {}
|
14
|
+
rows["A1"] = {'B'=>
|
15
|
+
{'A'=> ['5',6],
|
16
|
+
'C'=> {'F'=>'1','G'=>'2'},
|
17
|
+
'D'=> {'H'=>'3','I'=>'4'}
|
18
|
+
},
|
19
|
+
'X'=>[1,3,55.55]}
|
20
|
+
rows["A2"] = {'B'=>
|
21
|
+
{'C'=> {'F'=>'11','G2'=>'22'},
|
22
|
+
'D'=> {'H'=>'33','I2'=>{'a'=>'44','b'=>'66'}},
|
23
|
+
'E'=> '55'},
|
24
|
+
'X'=>[2.3,5.111,1,4]}
|
25
|
+
tex.table(rows,"hierarchical headers", "Rows")
|
26
|
+
|
27
|
+
File.open("saved_table.dat","r") do |f|
|
28
|
+
old_rows = Marshal::load(f)
|
29
|
+
rows.merge!(old_rows)
|
30
|
+
end
|
31
|
+
tex.table(rows,"both tables",:rowTitle=>"Instance") do |x,y|
|
32
|
+
order = %w{X B C D E G F H col1 col2 col3 Col3}
|
33
|
+
if order.index(x) && order.index(y)
|
34
|
+
order.index(x) <=> order.index(y)
|
35
|
+
else
|
36
|
+
x <=> y
|
37
|
+
end
|
38
|
+
end
|
39
|
+
tex.close
|
40
|
+
|
data/lib/latex.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Copyright (c) 2004 Christian Bang <cbang AT web.de> and Frank Hutter
|
2
2
|
#
|
3
|
-
# Version 0.1.
|
3
|
+
# Version 0.1.2
|
4
4
|
#
|
5
5
|
# All rights reserved. You can redistribute and/or modify it under the same terms as Ruby.
|
6
6
|
#
|
@@ -28,7 +28,7 @@ end
|
|
28
28
|
# You may want to quote underscores ('_') in some Latex code you create. For this use String.escape_ which
|
29
29
|
# is available with this file.
|
30
30
|
class LatexFile < File
|
31
|
-
Header = Struct.new(:name, :children)
|
31
|
+
Header = Struct.new(:name, :align, :children)
|
32
32
|
|
33
33
|
# the default table font size, default is nil which means the Latex default. See #table for possible values
|
34
34
|
attr_accessor :defaultTableFontSize
|
@@ -38,18 +38,22 @@ class LatexFile < File
|
|
38
38
|
@@default_extras = {:fontsize => "10pt" }
|
39
39
|
attr_reader :extras
|
40
40
|
|
41
|
+
@default_table_align = 'c'
|
42
|
+
# The default table alignment is <tt>'c'</tt> but can be changed.
|
43
|
+
attr_accessor :default_table_align
|
44
|
+
|
41
45
|
# Open a new latex-file for writing.
|
42
46
|
# +extras+ is an optional hash that may contain the following flags
|
43
47
|
# <tt>:landscape</tt>:: turns all pages 90�
|
44
48
|
# <tt>:twocolumn</tt>:: the whole document has two columns
|
45
49
|
# <tt>extras[:fontsize]</tt>:: string containing the font size like "10pt"
|
46
50
|
# === Example:
|
47
|
-
# f = LatexFile.new("test.tex",
|
51
|
+
# f = LatexFile.new("test.tex", :twocolumn => true, :fontsize => "11pt")
|
48
52
|
def initialize(filename, extras = nil)
|
49
53
|
super(filename,"w") # open a file for write access
|
50
54
|
@extras = extras || Hash.new
|
51
55
|
#use defaults for unused entries:
|
52
|
-
|
56
|
+
@@default_extras.each_key{|key| @extras[key] ||= @@default_extras[key] }
|
53
57
|
@indent = 0 # indent lines in blocks
|
54
58
|
|
55
59
|
@usePackages = @extras[:usePackages] || @@defaultUsePackages
|
@@ -194,12 +198,12 @@ class LatexFile < File
|
|
194
198
|
#+header+:: is of type +Header+: (name, children)
|
195
199
|
def getNumColsOfHeader(header)
|
196
200
|
header.children.inject(0) do |numChildren, child|
|
197
|
-
numChildren + (
|
201
|
+
numChildren + (child.children ? getNumColsOfHeader(child) : 1)
|
198
202
|
end
|
199
203
|
end
|
200
204
|
private :getNumColsOfHeader
|
201
205
|
|
202
|
-
#+
|
206
|
+
#+list+:: must contain hashes as values for all keys.
|
203
207
|
#These child hashes will be joined/merged to one big hash.
|
204
208
|
#The actual leafes will be ignored so that only the header remain.
|
205
209
|
def getHeaderMergedHash(list)
|
@@ -217,7 +221,11 @@ class LatexFile < File
|
|
217
221
|
#return list if nothingToMerge
|
218
222
|
return nil if nothingToMerge #return only header tree without any data
|
219
223
|
toMerge.each_pair do |key,value|
|
220
|
-
|
224
|
+
if key.class == Symbol
|
225
|
+
merged[key] = value unless merged[key]
|
226
|
+
else
|
227
|
+
merged[key] = getHeaderMergedHash(value)
|
228
|
+
end
|
221
229
|
end
|
222
230
|
return merged
|
223
231
|
end
|
@@ -228,16 +236,27 @@ class LatexFile < File
|
|
228
236
|
#Given a list of hashes, initially a hash-list of each row it
|
229
237
|
#returns a sorted tree representation - a headerList.
|
230
238
|
#+sort_block+:: a block that compares header names
|
239
|
+
#side effects::
|
240
|
+
# deletes :align entries from the +hash+ and transforms
|
241
|
+
# hash[:value] = value hashes to normal entries
|
231
242
|
def hash2HeaderList(hash, sort_block = @@default_sort)
|
232
243
|
headerList = []
|
233
244
|
entries = hash.to_a
|
234
|
-
entries.sort!
|
245
|
+
entries.sort! do |x,y| sort_block.call(x[0],y[0])
|
246
|
+
end
|
235
247
|
for key,value in entries
|
236
248
|
if value.class == Hash
|
237
|
-
|
238
|
-
|
249
|
+
align = value.delete(:align) || @default_table_align
|
250
|
+
align = align[0] if align.class == Array
|
251
|
+
if value[:value] #transform hashes with :value keys to normal entries
|
252
|
+
hash[key] = value = value[:value]
|
253
|
+
headerList << Header.new(key,align,nil)
|
254
|
+
else
|
255
|
+
subtree = hash2HeaderList(value, sort_block)
|
256
|
+
headerList << Header.new(key,align,subtree)
|
257
|
+
end
|
239
258
|
else
|
240
|
-
headerList << key
|
259
|
+
headerList << Header.new(key,@default_table_align,nil)
|
241
260
|
end
|
242
261
|
end
|
243
262
|
return headerList
|
@@ -257,11 +276,14 @@ class LatexFile < File
|
|
257
276
|
nextLevel = [] # collects the children nodes of all nodes processed (BFS)
|
258
277
|
hasChildrenInNextLevel = false
|
259
278
|
for header in headerList
|
260
|
-
if header.
|
261
|
-
line << header
|
262
|
-
nextLevel
|
279
|
+
if header.is_a?(Array) and header[0] == "~"
|
280
|
+
line << header
|
281
|
+
nextLevel << header # insert this for lines below this
|
282
|
+
elsif header.children == nil # leaf node ?
|
283
|
+
line << [header.name, header.align]
|
284
|
+
nextLevel << ["~",header.align] # insert this for lines below this
|
263
285
|
else
|
264
|
-
line << [header.name, getNumColsOfHeader(header)]
|
286
|
+
line << [header.name, header.align, getNumColsOfHeader(header)]
|
265
287
|
nextLevel += header.children
|
266
288
|
hasChildrenInNextLevel = true
|
267
289
|
end
|
@@ -280,10 +302,10 @@ class LatexFile < File
|
|
280
302
|
paths = []
|
281
303
|
path_prefix = path_prefix || []
|
282
304
|
for header in headerList
|
283
|
-
if header.
|
305
|
+
if header.children
|
284
306
|
paths += getLeafColumns(header.children, path_prefix + [header.name])
|
285
307
|
else #header is not of class Header but a leaf header (string)
|
286
|
-
paths << path_prefix + [header]
|
308
|
+
paths << path_prefix + [header.name]
|
287
309
|
end
|
288
310
|
end
|
289
311
|
return paths
|
@@ -341,6 +363,9 @@ class LatexFile < File
|
|
341
363
|
# <tt>:header_hlines</tt>::
|
342
364
|
# If +true+, then horizontal lines between headers of different depths are drawn.
|
343
365
|
# Default is +false+ (no horizontal header lines).
|
366
|
+
# <tt>:rowAlign</tt>::
|
367
|
+
# Alignment of the column containing the row names. Values are 'r','c','l'.
|
368
|
+
# See also the attribute +default_table_align+.
|
344
369
|
#
|
345
370
|
# === Example:
|
346
371
|
# require 'latex'
|
@@ -355,9 +380,22 @@ class LatexFile < File
|
|
355
380
|
# order = %w{A X B C D E}
|
356
381
|
# (order.index(x) && order.index(y)) ? order.index(x) <=> order.index(y) : x <=> y
|
357
382
|
# end
|
358
|
-
# tex.table(rows,"special ordering", :rowTitle=>"Instance", :sort => tableSort)
|
383
|
+
# tex.table(rows,"special ordering", :rowTitle=>"Instance", :sort => tableSort)
|
384
|
+
#
|
385
|
+
# === Column alignment:
|
386
|
+
# By default alignment is centered. You can change this for all columns using the attribute
|
387
|
+
# +default_table_align+.
|
388
|
+
# The alignment can also be changed for each column separately:
|
389
|
+
# Headers can be aligned as demonstrated in the following examples:
|
390
|
+
# rows['1'] = {'Main Header' => {:align => 'l', 'A' => '5','B' => '6'}}
|
391
|
+
# This affects only the header and not the columns, because this is no final column header.
|
392
|
+
# Subheader and so the final columns themselves are aligned as follows:
|
393
|
+
# rows['1'] = {'Main Header' => {'A' => {:value => '5', :align => 'l'} ,'B' => '6'}}
|
394
|
+
# rows['2'] = {'Main Header' => {'A' => '77','B' => '8'}}
|
395
|
+
# As you can see it is only needed to define the alignment of a column once. It can be done
|
396
|
+
# as often as you like but only one alignment definition is used.
|
359
397
|
def table(entries, caption, *args)
|
360
|
-
tableValidArgs = [:rowTitle, :label, :newTableThreshold, :placement, :empty, :sort, :landscape, :fontSize, :grouping, :header_hlines]
|
398
|
+
tableValidArgs = [:rowTitle, :label, :newTableThreshold, :placement, :empty, :sort, :landscape, :fontSize, :grouping, :header_hlines, :rowAlign]
|
361
399
|
# raise(ArgumentError,"Too many arguments Latex.table", caller) unless args.length <= 1
|
362
400
|
hash = {}
|
363
401
|
args = if args[0].kind_of?(Hash)
|
@@ -377,6 +415,7 @@ class LatexFile < File
|
|
377
415
|
@tableLandscape = args[:landscape]
|
378
416
|
@tableFontSize = args[:fontSize] || @defaultTableFontSize
|
379
417
|
@header_hlines = args[:header_hlines]
|
418
|
+
@rowAlign = args[:rowAlign] || @default_table_align
|
380
419
|
|
381
420
|
#access an element in the table which is located in row _rowName_ and in a column
|
382
421
|
#that is defined by a _path_ through the headers that can be obtained with
|
@@ -387,6 +426,7 @@ class LatexFile < File
|
|
387
426
|
entry = entry[key]
|
388
427
|
return [] unless entry
|
389
428
|
end
|
429
|
+
entry = entry[:value] if entry.is_a?(Hash)
|
390
430
|
return entry.is_a?(Array) ? entry : [entry]
|
391
431
|
end
|
392
432
|
|
@@ -395,7 +435,9 @@ class LatexFile < File
|
|
395
435
|
puts "\n\\begin{table}[#{placement}]\n\\begin{center}"
|
396
436
|
puts "\\#{@tableFontSize}" if @tableFontSize
|
397
437
|
print " "*@indent + "\\begin{tabular}{|"
|
398
|
-
print
|
438
|
+
# print the alignment {c,r,l} for each leaf column
|
439
|
+
print "#{@rowAlign}|" # the first column with the row names
|
440
|
+
headerLines[-1].each {|headerName, colAlign| print "#{colAlign}|" }
|
399
441
|
puts "}"
|
400
442
|
currentHeaderRowNumber = 0
|
401
443
|
puts "\\hline"
|
@@ -408,11 +450,11 @@ class LatexFile < File
|
|
408
450
|
end
|
409
451
|
currentColumn = 2
|
410
452
|
cline = ""
|
411
|
-
print headerLine.map {|headerName, columns|
|
453
|
+
print headerLine.map {|headerName, align, columns|
|
412
454
|
raise(FormatError, "Invalid format: #{headerName.inspect} contains % that is not sufficiently quoted for latex.", caller) if headerName =~ /[^\\]%|^%/
|
413
455
|
if columns
|
414
456
|
cline += "\\cline{#{currentColumn}-#{(currentColumn+=columns)-1}}" if @header_hlines
|
415
|
-
"\\multicolumn{#{columns}}{
|
457
|
+
"\\multicolumn{#{columns}}{#{align}|}{#{headerName}}"
|
416
458
|
else
|
417
459
|
currentColumn += 1
|
418
460
|
if currentHeaderRowNumber == headerLines.length-1 || headerName == "~"
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.1
|
|
3
3
|
specification_version: 1
|
4
4
|
name: latex
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.1.
|
7
|
-
date: 2004-
|
6
|
+
version: 0.1.2
|
7
|
+
date: 2004-10-19
|
8
8
|
summary: Latex is a LaTeX text generation library for Ruby.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -13,7 +13,7 @@ email: cbang AT web.de
|
|
13
13
|
homepage: http://latex.rubyforge.org
|
14
14
|
rubyforge_project: latex
|
15
15
|
description:
|
16
|
-
autorequire: latex
|
16
|
+
autorequire: latex
|
17
17
|
default_executable:
|
18
18
|
bindir: bin
|
19
19
|
has_rdoc: true
|
@@ -29,7 +29,17 @@ files:
|
|
29
29
|
- lib/latex.rb
|
30
30
|
- README
|
31
31
|
- LICENSE.txt
|
32
|
+
- ChangeLog
|
33
|
+
- examples/saved_table.dat
|
34
|
+
- examples/test-latex.rb.~1.3.~
|
32
35
|
- examples/test-latex.rb
|
36
|
+
- examples/latextest.aux
|
37
|
+
- examples/latextest.dvi
|
38
|
+
- examples/latextest.log
|
39
|
+
- examples/latextest.out
|
40
|
+
- examples/latextest.tex
|
41
|
+
- examples/latextest.tex~
|
42
|
+
- examples/latex.rb
|
33
43
|
test_files: []
|
34
44
|
rdoc_options: []
|
35
45
|
extra_rdoc_files: []
|