Codebase list liblatex-table-perl / 975c772
[svn-inject] Installing original source of liblatex-table-perl Salvatore Bonaccorso 14 years ago
42 changed file(s) with 8105 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 use 5.008;
1 use strict;
2 use warnings;
3 use Module::Build;
4
5 my $builder = Module::Build->new(
6 module_name => 'LaTeX::Table',
7 license => 'perl',
8 dist_author => 'Markus Riester <mriester@gmx.de>',
9 dist_version_from => 'lib/LaTeX/Table.pm',
10 requires => {
11 'perl' => '5.8.0',
12 'English' => 0,
13 'Moose' => 0,
14 'Moose::Policy::FollowPBP' => 0,
15 'Module::Pluggable' => 0,
16 'Scalar::Util' => 0,
17 'Carp' => 0,
18 'version' => 0,
19 'Template' => 0,
20 },
21 build_requires => {
22 'Test::More' => 0,
23 'Test::NoWarnings' => 0,
24 'File::Spec' => 0,
25 },
26 recommends => {
27 'Text::CSV' => 0,
28 'LaTeX::Driver' => 0,
29 'LaTeX::Encode' => 0,
30 'Getopt::Long' => 0,
31 'Number::Format' => 0,
32 },
33 script_files => [ 'bin/csv2pdf', 'bin/ltpretty' ],
34 add_to_cleanup => [ 'LaTeX-Table-*' ],
35 );
36
37 $builder->create_build_script();
0 Revision history for LaTeX-Table
1
2 0.9.15 Fri May 29 10:00:00 2009
3 - MISSING_VALUE in coldef_strategy
4 - width and longtable
5 - removed deprecated feature textwrap
6 - changed optional requirement from Text::CSV_XS to Text::CSV
7 - csv2pdf: Meyrin default.
8 - POD cleanups
9
10 0.9.14 Tue Feb 24 10:00:00 2009
11 - Meyrin now default theme
12 - sideways now works also with xtab (lscape package)
13 - longtable package
14 - POD cleanups
15
16 0.9.13 Wed Feb 4 12:00:00 2009
17 - continued, continuedmsg options
18 - Minor Bug fixed: maincaption required caption.
19 - renamed *_LINES to *_RULES
20 - RULES_CMD in themes
21 - examples.pdf nicer
22
23 0.9.12 Fri Jan 30 15:00:00 2009
24 - fontfamily
25 - API change: size renamed to fontsize
26 - custom_template
27 - themes can now define rule width and color (only global)
28 - Muenchen, NYC3, NYC4, Redmond and Redmond2 Themes
29 - Perl-Critic-1.094001 passes
30
31 0.9.11 Sat Jan 3 13:00:00 2009
32 - tabulary package
33 - STUB_ALIGN in themes
34 - POD corrections
35
36 0.9.10 Sun Nov 23 02:15:00 2008
37 - removed unnecessary blanks and spaces in LaTeX output
38 - LaTeX output aligned
39 - Meyrin Theme
40 - POD corrections
41
42 0.9.9 Wed Nov 12 12:01:00 2008
43 - removed Readonly, caused cpantester fails
44 - shortcaption
45 - left
46 - right
47 - moved more code in templates
48 - ctable now uses tabularx
49 - NYC2 theme
50
51 0.9.8 Sat Nov 8 11:01:00 2008
52 - support for the ctable package
53 - sideways option
54 - star option
55
56 0.9.7 Wed Nov 5 11:01:00 2008 (Obama wins :))
57 - Switched to Moose
58 - themes now definable as modules.
59 - csv2pdf. Lots of new features.
60
61 0.9.6 Thu Oct 7 8:44:00 2008
62 - Bugfix: extracolsep after first column
63 - removed Fatal dependency (which is deprecated)
64 - Standard LONG regex now requires at least two words (thanks to salva on
65 perlmonks)
66 - removed color LaTeX package dependency. xcolor is enough
67
68 0.9.5 Thu Oct 2 18:30:00 2008
69 - POD corrections
70 - new, common exception format for invalid option usage
71 - environment must be true for xtab packages
72 - \belowcaptionskip instead of 10pt in tablehead, caption_top
73 - custom_tabular_environment (e.g. for mpxtabular)
74
75 0.9.4 Wed Oct 1 18:30:00 2008
76 - coldef_strategy: column types can be defined
77 - empty rows in headers now also produce horizontal lines for consistency
78 - now data is only analyzed once (was twice in xtab)
79 - tableheadmsg
80 - Bugfix: latex commands in data counted as line (problem for
81 _MUST_MATCH_ALL)
82 - Bugfix: columns_like_header columns always left-justified
83 - a few more tests
84
85 0.9.3 Fri Sep 26 14:00:00 2008
86 - leading/trailing spaces in default NUMBER regex allowed
87 - coldef_strategy: suffix _MUST_MATCH_ALL now defines whether the
88 specified type must match all cells in a column (or at least one).
89 - ltpretty: howtos for vim and emacs
90 - EXTRA_ROW_HEIGHT. now NYC theme looks better
91 - header_sideways
92 - API change: * DEFAULT renamed to DEFAULT_COL
93 * DEFAULT_X renamed to DEFAULT_COL_X
94 * IS_A_NUMBER renamed to NUMBER
95 * IS_LONG renamed to LONG and is now a regular
96 expression
97
98 Sorry, I think it is the last big change before 1.0. It was
99 necessary because I will add the functionality to define column
100 types (like NUMBER and LONG) and this needs a cleaner interface.
101 - Bugfix: first column always left-justified
102 - a few more tests
103
104 0.9.2 Thu Sep 18 14:00:00 2008
105 - POD corrections
106 - added ltpretty. I use it in vim to format my tables with LaTeX::Table
107
108 0.9.1 Wed Aug 27 21:38:00 2008
109 - Bugfix: no midrule without header
110 - Bugfix: calculation of column ids (callback, coldef_strategy) now
111 supports multicolumn shortcuts
112 - Bugfix: specified Latex commands in data (with single column arrays)
113 counted as rows (problem for DATA_BG_COLOR_ODD/EVEN)
114 - colums_like_header()
115 - more tests
116 - Paris Theme
117 - POD corrections
118
119 0.9.0 Sat Aug 23 19:00:00 2008
120 - caption_top
121 - themes can now define header font color and bgcolors
122 - multicol shortcut now automatically adds vertical lines
123 - resizebox
124 - Bugfix: centering now only in std.
125 - Bugfix: callback function could destroy our multicolumn shortcut
126 - Bugfix: callback function in header only applied when HEADER_CENTERED
127 in theme
128 - API change: text_wrap now deprecated. tabularx produces so much nicer
129 tables and it does not break the callback row ids. If you really think this
130 is useful somehow, drop me a mail
131
132 0.8.0 Thu Aug 21 14:30:00 2008
133 - centering instead of center
134 - Bugfix: callback function overwrote values in arrays
135 - maincaption not bold in Zurich
136 - API change: table_environment now environment, environment can be chosen, e.g.
137 'sidewaystable'
138 - API change: tablepos renamed to position
139 - API change: tabledef renamed to coldef
140 - API change: tabledef_strategy renamed to coldef_strategy
141 - tabularx package
142 - default value for long col now 30
143 - POD updates
144 - examples.pdf better
145
146 0.7.0 Tue Aug 19 21:15:00 2008
147 - plain theme
148 - POD updates
149
150 0.6.3 Fri Jul 25 21:15:00 2008
151 - commands now printed without formatting
152 - removed the simpsons synopsis
153 - Perl::Critic passes again
154
155 0.6.2 Wed Apr 16 11:28:00 2008
156 - made new Perl::Critic happy
157 - Bugfix: \hline in xtab/booktabs
158
159 0.6.1 Tue Mar 04 16:00:00 2008
160 - added kwalitee test
161 - added perl 5.8 dependency
162 - added licence in Makefile.PL
163 - Bugfix: \hline instead of \midrule
164
165 0.6.0 Wed Nov 07 15:00:00 2007
166 - support for booktabs.sty
167 - Zurich standard
168 - width
169 - regex IS_A_NUMBER compiled only once (same bug again)
170
171 0.5.2 Tue Nov 06 18:00:00 2007
172 - tests produced latextable.tex in /
173 - replaced Regexp::Common with perlfaq4 regexes. MUCH faster now.
174 - new theme Berlin
175 - custom IS_A_NUMBER regex ignored
176 - cvs2pdf:
177 - support for themes
178 - Berlin default (first column contains data in CSV)
179
180 0.5.1 Tue Nov 06 12:00:00 2007
181 - xtab: last page not centered when center=1
182 - csv2pdf:
183 - typos in POD
184 - --man not working
185 - moved to directory bin
186 - removed "continued on next page" tabletail
187 - xentrystretch 0.001 (more rows per page)
188
189 0.5.0 Mon Nov 05 15:00:00 2007
190 - die when value in cell is undef (fixes many warnings and funny
191 results)
192 - tabletail should work now
193 - added csv2pdf
194
195 0.4.0 Sat Oct 20 18:04:00 2007
196 - tabledef_strategy
197
198 0.3.0 Sat Oct 20 18:04:00 2007
199 - generate() tests data and header
200 - themes test
201 - pod corrections
202
203 0.2.1 Fri Oct 19 18:02:00 2007
204 - Bugfix: callback $is_header == 1 in data
205
206 0.2.0 Fri Oct 19 18:00:00 2007
207 - use Text::Wrap for wrapping lines
208 - callback
209 - xtab tests
210
211 0.1.1 Thu Sep 20 18:03:00 2007
212 - minor POD corrections
213 - Bugfixes:
214 * perlcritic optional,
215 passes now with severity 1
216
217 0.1.0 Thu Sep 20 12:30:00 2007
218 - API CHANGE: header and data now options
219 - label optional
220 - caption optional
221 - maincaption optional
222 - custom themes can be set in new()
223 - POD improvements
224 - more tests
225 - table environment optional
226 - added examples.pdf
227 - Bugfixes:
228 * META.yml missing
229
230 0.0.3 Thu Mar 5 18:10:11 2007
231 - t/perlcritic.t: required Test::Perl::Critic
232
233 0.0.2 Wed Feb 28 16:52:00 2007
234 - Added missing dependencies in Build.PL
235 - Test::Perl::Critic passed
236
237 0.0.1 Thu Aug 3 12:10:07 2006
238 Initial release.
239
0 Preamble
1
2 The intent of this document is to state the conditions under which a Package
3 may be copied, such that the Copyright Holder maintains some semblance of
4 artistic control over the development of the package, while giving the users
5 of the package the right to use and distribute the Package in a more-or-less
6 customary fashion, plus the right to make reasonable modifications.
7
8 Definitions:
9
10 "Package" refers to the collection of files distributed by the Copyright
11 Holder, and derivatives of that collection of files created through textual
12 modification.
13
14 "Standard Version" refers to such a Package if it has not been modified, or
15 has been modified in accordance with the wishes of the Copyright Holder as
16 specified below.
17
18 "Copyright Holder" is whoever is named in the copyright or copyrights for the
19 package.
20
21 "You" is you, if you're thinking about copying or distributing this Package.
22
23 "Reasonable copying fee" is whatever you can justify on the basis of media
24 cost, duplication charges, time of people involved, and so on. (You will not
25 be required to justify it to the Copyright Holder, but only to the computing
26 community at large as a market that must bear the fee.)
27
28 "Freely Available" means that no fee is charged for the item itself, though
29 there may be fees involved in handling the item. It also means that recipients
30 of the item may redistribute it under the same conditions they received it.
31
32 1. You may make and give away verbatim copies of the source form of the
33 Standard Version of this Package without restriction, provided that you
34 duplicate all of the original copyright notices and associated disclaimers.
35
36 2. You may apply bug fixes, portability fixes and other modifications derived
37 from the Public Domain or from the Copyright Holder. A Package modified in
38 such a way shall still be considered the Standard Version.
39
40 3. You may otherwise modify your copy of this Package in any way, provided
41 that you insert a prominent notice in each changed file stating how and when
42 you changed that file, and provided that you do at least ONE of the following:
43
44 a) place your modifications in the Public Domain or otherwise make them Freely
45 Available, such as by posting said modifications to Usenet or an equivalent
46 medium, or placing the modifications on a major archive site such as
47 uunet.uu.net, or by allowing the Copyright Holder to include your
48 modifications in the Standard Version of the Package. b) use the modified
49 Package only within your corporation or organization. c) rename any
50 non-standard executables so the names do not conflict with standard
51 executables, which must also be provided, and provide a separate manual page
52 for each non-standard executable that clearly documents how it differs from
53 the Standard Version. d) make other distribution arrangements with the
54 Copyright Holder. 4.You may distribute the programs of this Package in object
55 code or executable form, provided that you do at least ONE of the following:
56
57 a) distribute a Standard Version of the executables and library files,
58 together with instructions (in the manual page or equivalent) on where to get
59 the Standard Version. b) accompany the distribution with the machine-readable
60 source of the Package with your modifications. c) give non-standard
61 executables non-standard names, and clearly document the differences in manual
62 pages (or equivalent), together with instructions on where to get the Standard
63 Version. d) make other distribution arrangements with the Copyright Holder.
64 5. You may charge a reasonable copying fee for any distribution of this
65 Package. You may charge any fee you choose for support of this Package. You
66 may not charge a fee for this Package itself. However, you may distribute this
67 Package in aggregate with other (possibly commercial) programs as part of a
68 larger (possibly commercial) software distribution provided that you do not
69 advertise this Package as a product of your own. You may embed this Package's
70 interpreter within an executable of yours (by linking); this shall be
71 construed as a mere form of aggregation, provided that the complete Standard
72 Version of the interpreter is so embedded.
73
74 6. The scripts and library files supplied as input to or produced as output
75 from the programs of this Package do not automatically fall under the
76 copyright of this Package, but belong to whoever generated them, and may be
77 sold commercially, and may be aggregated with this Package. If such scripts or
78 library files are aggregated with this Package via the so-called "undump" or
79 "unexec" methods of producing a binary executable image, then distribution of
80 such an image shall neither be construed as a distribution of this Package nor
81 shall it fall under the restrictions of Paragraphs 3 and 4, provided that you
82 do not represent such an executable image as a Standard Version of this
83 Package.
84
85 7. C subroutines (or comparably compiled subroutines in other languages)
86 supplied by you and linked into this Package in order to emulate subroutines
87 and variables of the language defined by this Package shall not be considered
88 part of this Package, but are the equivalent of input as in Paragraph 6,
89 provided these subroutines do not change the language in any way that would
90 cause it to fail the regression tests for the language.
91
92 8. Aggregation of this Package with a commercial distribution is always
93 permitted provided that the use of this Package is embedded; that is, when no
94 overt attempt is made to make this Package's interfaces visible to the end
95 user of the commercial distribution. Such use shall not be construed as a
96 distribution of this Package.
97
98 9. The name of the Copyright Holder may not be used to endorse or promote
99 products derived from this software without specific prior written permission.
100
101 10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
102 WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
103 MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
104
105 The End
0 Build.PL
1 Changes
2 MANIFEST
3 LICENSE
4 META.yml
5 Makefile.PL
6 README
7 TODO
8 bin/csv2pdf
9 bin/ltpretty
10 examples/generate_examples.pl
11 examples/imdbtop40.dat
12 examples/examples.pdf
13 lib/LaTeX/Table.pm
14 lib/LaTeX/Table/Types/TypeI.pm
15 lib/LaTeX/Table/Types/Ctable.pm
16 lib/LaTeX/Table/Types/Longtable.pm
17 lib/LaTeX/Table/Types/Std.pm
18 lib/LaTeX/Table/Types/Xtab.pm
19 lib/LaTeX/Table/Themes/ThemeI.pm
20 lib/LaTeX/Table/Themes/Beamer.pm
21 lib/LaTeX/Table/Themes/Booktabs.pm
22 lib/LaTeX/Table/Themes/Classic.pm
23 lib/LaTeX/Table/Themes/Modern.pm
24 t/00.load.t
25 t/10.table-ctable.t
26 t/10.table-custom.t
27 t/10.table-std.t
28 t/10.table-xtab.t
29 t/20.mcdef.t
30 t/30.exceptions.t
31 t/40.miscprivates.t
32 t/50.synopsis.t
33 t/60.coldef.t
34 t/70.callback.t
35 t/80.themes.t
36 t/90.combat.t
37 t/lib/MyThemes/Custom.pm
38 t/perlcritic.t
39 t/perlcriticrc
40 t/pod-coverage.t
41 t/pod.t
0 ---
1 name: LaTeX-Table
2 version: 0.9.15
3 author:
4 - 'Markus Riester <mriester@gmx.de>'
5 abstract: Perl extension for the automatic generation of LaTeX tables.
6 license: perl
7 resources:
8 license: http://dev.perl.org/licenses/
9 requires:
10 Carp: 0
11 English: 0
12 Module::Pluggable: 0
13 Moose: 0
14 Moose::Policy::FollowPBP: 0
15 Scalar::Util: 0
16 Template: 0
17 perl: 5.8.0
18 version: 0
19 build_requires:
20 File::Spec: 0
21 Test::More: 0
22 Test::NoWarnings: 0
23 recommends:
24 Getopt::Long: 0
25 LaTeX::Driver: 0
26 LaTeX::Encode: 0
27 Number::Format: 0
28 Text::CSV: 0
29 provides:
30 LaTeX::Table:
31 file: lib/LaTeX/Table.pm
32 version: 0.9.15
33 LaTeX::Table::Themes::Beamer:
34 file: lib/LaTeX/Table/Themes/Beamer.pm
35 version: 1298
36 LaTeX::Table::Themes::Booktabs:
37 file: lib/LaTeX/Table/Themes/Booktabs.pm
38 version: 1326
39 LaTeX::Table::Themes::Classic:
40 file: lib/LaTeX/Table/Themes/Classic.pm
41 version: 1151
42 LaTeX::Table::Themes::Modern:
43 file: lib/LaTeX/Table/Themes/Modern.pm
44 version: 1298
45 LaTeX::Table::Themes::ThemeI:
46 file: lib/LaTeX/Table/Themes/ThemeI.pm
47 version: 1312
48 LaTeX::Table::Types::Ctable:
49 file: lib/LaTeX/Table/Types/Ctable.pm
50 version: 1307
51 LaTeX::Table::Types::Longtable:
52 file: lib/LaTeX/Table/Types/Longtable.pm
53 version: 1313
54 LaTeX::Table::Types::Std:
55 file: lib/LaTeX/Table/Types/Std.pm
56 version: 1307
57 LaTeX::Table::Types::TypeI:
58 file: lib/LaTeX/Table/Types/TypeI.pm
59 version: 1612
60 LaTeX::Table::Types::Xtab:
61 file: lib/LaTeX/Table/Types/Xtab.pm
62 version: 1564
63 generated_by: Module::Build version 0.33
64 meta-spec:
65 url: http://module-build.sourceforge.net/META-spec-v1.4.html
66 version: 1.4
0 use 5.008;
1
2 use strict;
3 use warnings;
4 use ExtUtils::MakeMaker;
5
6 WriteMakefile(
7 NAME => 'LaTeX::Table',
8 AUTHOR => 'Markus Riester <mriester@gmx.de>',
9 VERSION_FROM => 'lib/LaTeX/Table.pm',
10 ABSTRACT_FROM => 'lib/LaTeX/Table.pm',
11 ((ExtUtils::MakeMaker->VERSION() gt '6.30') ?
12 ('LICENSE' => 'perl') : ()),
13 PL_FILES => {},
14 PREREQ_PM => {
15 'Test::More' => 0,
16 'Test::NoWarnings' => 0,
17 'Moose' => 0,
18 'Moose::Policy::FollowPBP' => 0,
19 'Module::Pluggable' => 0,
20 'Scalar::Util' => 0,
21 'version' => 0,
22 'Template' => 0,
23 },
24 EXE_FILES => [ 'bin/csv2pdf', 'bin/ltpretty' ],
25 dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', },
26 clean => { FILES => 'LaTeX-Table-*' },
27 );
0 LaTeX-Table version 0.9.15
1
2 This module supports multipage tables via the xtab and the longtable package.
3 For publication quality tables it utilizes the booktabs package. It also
4 supports the tabularx and tabulary packages for nicer fixed-width tables.
5 Furthermore, it supports the colortbl package for colored tables optimized for
6 presentations. The powerful new ctable package is supported and especially
7 recommended when footnotes are needed. LaTeX::Table ships with some
8 predefined, good looking themes.
9
10 INSTALLATION
11
12 To install this module, run the following commands:
13
14 perl Build.PL
15 ./Build
16 ./Build test
17 ./Build install
18
19
20 Alternatively, to install with ExtUtils::MakeMaker, you can use the following
21 commands:
22
23 perl Makefile.PL
24 make
25 make test
26 make install
27
28
29 Now start the script generate_examples.pl in the examples directory of this
30 distibution.
31
32 perl generate_examples.pl
33
34 This script generates some LaTeX files with some example tables.
35 Now please compile these examples with LaTeX and check if all tables look ok:
36
37 latex examples.tex
38 xdvi examples.dvi
39
40
41 PROGRAMS
42
43 This module ships with two small utilities. The first, csv2pdf is a CSV to PDF
44 converter. It is only about 100 lines of code short and only meant as an
45 example application, but it is already very powerful. It requires Getopt::Long,
46 Text::CSV, LaTeX::Encode and LaTeX::Driver, which are not installed during the
47 installation of this module.
48
49 The second utility is ltpretty. It takes a lazy formatted LaTeX table from
50 STDIN (typically piped from Vim or emacs) and outputs a completely formatted
51 table. This makes this module not only useful for automatically generated
52 reports, but also saves a lot of typing work in creating custom tables.
53
54
55 DEPENDENCIES
56
57 Carp
58 Class::Std
59 English
60 Readonly
61 Scalar::Util
62 Text::Wrap
63
64 COPYRIGHT AND LICENCE
65
66 Copyright (C) 2006-2009, Markus Riester
67
68 This library is free software; you can redistribute it and/or modify
69 it under the same terms as Perl itself.
0 before 1.0
1
2 - fine tune default parameters
3 - nicer examples.pdf (started)
4 - make it possible to use custom templates (done, now document it)
5 - remove deprecated code (release candidate 1)
6
7 after 1.0
8
9 - code cleanup (use more Moose features, e.g. validation)
10 - shortcut for multirows
0 #!/usr/bin/perl
1
2 #############################################################################
3 # $Author: markus $
4 # $Date: 2009-05-29 10:38:31 +0200 (Fri, 29 May 2009) $
5 # $Revision: 1616 $
6 #############################################################################
7
8 use strict;
9 use warnings;
10
11 use utf8;
12
13 use Fatal qw(open close);
14 use Getopt::Long;
15 use Pod::Usage;
16 use Carp;
17
18 use Text::CSV;
19 use File::Basename;
20 use Readonly;
21
22 use LaTeX::Table;
23 use LaTeX::Encode;
24 use LaTeX::Driver;
25
26 use version; our $VERSION = $LaTeX::Table::VERSION;
27
28 Readonly my $DEFAULT_XENTRYSTRETCH => -0.05;
29 Readonly my $DEFAULT_THEME => 'Meyrin';
30
31 my ( $infile, $outfile, $help, $man, $version );
32
33 my $sep_char = q{,};
34 my $latex_encode = 0;
35 my $landscape = 0;
36 my $outputlatex = 0;
37 my $theme = $DEFAULT_THEME;
38 my $title = 0;
39 my $coldef = 0;
40 my $header = 0;
41
42 my $options_ok = GetOptions(
43 'in=s' => \$infile,
44 'out=s' => \$outfile,
45 'sep_char=s' => \$sep_char,
46 'latex_encode' => \$latex_encode,
47 'landscape' => \$landscape,
48 'outputlatex' => \$outputlatex,
49 'theme=s' => \$theme,
50 'title=s' => \$title,
51 'coldef=s' => \$coldef,
52 'header=s' => \$header,
53 'help|?' => \$help,
54 'version|v' => \$version,
55 'man' => \$man,
56 ) or pod2usage(2);
57
58 if ($version) {
59 print "$0 $VERSION\n" or croak q{Can't print to stdout.};
60 exit;
61 }
62
63 if ($man) {
64 pod2usage( -exitstatus => 0, -verbose => 2 );
65 }
66 if ( $help || !defined $infile ) {
67 pod2usage(1);
68 }
69 if ( !defined $outfile ) {
70 $outfile = q{./} . fileparse( $infile, qw(csv txt dat) ) . '.pdf';
71 }
72
73 my $csv = Text::CSV->new(
74 { binary => 1,
75 sep_char => $sep_char,
76 allow_whitespace => 1
77 }
78 );
79
80 my @header;
81 my @data;
82
83 if ($header) {
84 my $status = $csv->parse($header);
85 @header = [ $csv->fields() ];
86 }
87
88 my $line_number = 0;
89
90 open my $IN, '<', $infile;
91 while ( my $line = <$IN> ) {
92 chomp $line;
93 my $status = $csv->parse($line);
94 if ( !$header && $line_number == 0 ) {
95 @header = [ $csv->fields() ];
96 }
97 else {
98 push @data, [ $csv->fields() ];
99 }
100 $line_number++;
101 }
102 close $IN;
103
104 my $table = LaTeX::Table->new(
105 { header => \@header,
106 data => \@data,
107 type => 'xtab',
108 xentrystretch => $DEFAULT_XENTRYSTRETCH,
109 tabletail => q{ },
110 theme => $theme,
111
112 # width => '\textwidth',
113 coldef => $coldef,
114 callback => sub {
115 my ( $row, $col, $value, $is_header ) = @_;
116 if ($latex_encode) {
117 return latex_encode($value);
118 }
119 return $value;
120 },
121 }
122 );
123
124 my $ls = q{};
125 my $lg = q{};
126 if ($landscape) {
127 $ls = '[landscape]';
128 $lg = '\usepackage[landscape]{geometry}';
129 }
130 my $tc = q{};
131 my $mtc = q{};
132
133 if ($title) {
134 $tc = '\title{' . $title . '}';
135 $mtc = '\maketitle';
136 }
137 my $code = '\documentclass' . $ls
138 . '{article}\usepackage{xtab}'
139 . $lg
140 . '\usepackage{booktabs}'
141 . '\usepackage{xcolor}'
142 . '\usepackage{colortbl}'
143 . '\usepackage{array}'
144 . '\usepackage{helvet}'
145 . $tc
146 . '\begin{document}'
147 . $mtc . "\n"
148 . $table->generate_string
149 . '\end{document}';
150
151 my $drv = LaTeX::Driver->new(
152 source => \$code,
153 output => $outfile,
154 format => 'pdf',
155 );
156 my $ok = $drv->run;
157
158 if ($outputlatex) {
159 print "$code" or croak q{Can't print to stdout.};
160 }
161
162 __END__
163
164 =head1 NAME
165
166 csv2pdf - A simple but yet powerful LaTeX::Table example application.
167
168 =head1 SYNOPSIS
169
170 csv2pdf [OPTIONS] --in in.csv [--out out.pdf]
171
172 =head1 OPTIONS
173
174 =over
175
176 =item C<--sep_char>
177
178 The separator character. Default comma ','.
179
180 =item C<--latex_encode>
181
182 Use L<LaTeX::Encode>.
183
184 =item C<--landscape>
185
186 Output the PDF in landscape orientation.
187
188 =item C<--theme>
189
190 The table theme. See L<LaTeX::Table>. Default I<Meyrin>.
191
192 =item C<--coldef>
193
194 The column definition, eg 'llp{5cm}'. If unset, guessed by L<LaTeX::Table>.
195
196 =item C<--title>
197
198 If set, then uses the specified string as title.
199
200 =item C<--header>
201
202 Instead of the first line, use the specified string as header.
203
204 --header "Header A, Header B, Header C"
205
206 The separator character must be the same as in the file. If unset, then the
207 first line is used as header.
208
209 =item C<--outputlatex>
210
211 Prints the LaTeX code to STDOUT.
212
213 =item C<--man>
214
215 Display manpage.
216
217 =item C<--version>
218
219 Print version number of this software.
220
221 =back
222
223 =head1 DESCRIPTION
224
225 Converts a CSV file to PDF. Requires LaTeX.
226
227 =head1 CONFIGURATION AND ENVIRONMENT
228
229 C<csv2pdf> does not support configuration files or environment variables.
230
231 =head1 DEPENDENCIES
232
233 LaTeX.
234
235 L<Fatal>, L<File::Basename>, L<Getopt::Long>, L<LaTeX::Driver>, L<LaTeX::Encode>, L<LaTeX::Table>,
236 L<Pod::Usage>, L<Readonly>, L<Text::CSV>
237
238 =head1 BUGS AND LIMITATIONS
239
240 No bugs have been reported.
241
242 Please report any bugs or feature requests to
243 C<bug-latex-table@rt.cpan.org>, or through the web interface at
244 L<http://rt.cpan.org>.
245
246 =head1 AUTHOR
247
248 Markus Riester C<< <mriester@gmx.de> >>
249
250 =head1 LICENSE AND COPYRIGHT
251
252 Copyright (c) 2006-2009, Markus Riester C<< <mriester@gmx.de> >>.
253
254 This program is free software; you can redistribute it and/or
255 modify it under the same terms as Perl itself. See L<perlartistic>.
256
257 =head1 DISCLAIMER OF WARRANTY
258
259 BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
260 FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
261 OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
262 PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
263 EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
264 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
265 ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
266 YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
267 NECESSARY SERVICING, REPAIR, OR CORRECTION.
268
269 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
270 WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
271 REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
272 LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
273 OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
274 THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
275 RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
276 FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
277 SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
278 SUCH DAMAGES.
279
280 =cut
281
282 # vim: ft=perl sw=4 ts=4 expandtab
0 #!/usr/bin/perl
1
2 #############################################################################
3 # $Author: markus $
4 # $Date: 2009-01-03 12:59:20 +0100 (Sat, 03 Jan 2009) $
5 # $Revision: 1259 $
6 #############################################################################
7
8 use strict;
9 use warnings;
10
11 use LaTeX::Table;
12 use Carp;
13
14 use version; our $VERSION = $LaTeX::Table::VERSION;
15
16 my $line_id = 0;
17 my @input;
18 my $paramline;
19
20 while (my $line = <>) {
21 chomp $line;
22 $line =~ s{\s+}{ }xmsg;
23 $line =~ s{\A \s* | \\ | \s* \z}{}xmsg;
24 if ($line_id == 0) { #first line contains the parameters
25 $paramline = $line;
26 }
27 else {
28 push @input, $line;
29 }
30 $line_id++;
31 }
32
33 # uncomment original input
34 _say( join q{}, map { "\n % $_" } ($paramline, @input) );
35
36 @input = map { [ split m{ & }xms ] } @input;
37
38 # store the paramline in a hash
39 my %params = map { _parse_param($_) } split m{ ; }xms, $paramline;
40
41 my $table = LaTeX::Table->new({
42 header => [ $input[0] ],
43 data => [ @input[1 .. $#input ] ],
44 %params,
45 });
46
47 _say("\n" . $table->generate_string());
48
49 sub _parse_param {
50 my ( $s ) = @_;
51 if ( $s =~ m{ \A (.*?) = (.*) \z}xms) {
52 return $1 => $2;
53 }
54 else {
55 croak q{Invalid parameter line};
56 }
57 return;
58 }
59
60 sub _say {
61 my ( $s ) = @_;
62 print "$s\n" or croak q{Can't print to stdout.};
63 return;
64 }
65
66 __END__
67
68 =head1 NAME
69
70 ltpretty - Use LaTeX::Table from within your text editor.
71
72 =head1 SYNOPSIS
73
74 ltpretty < lazytable
75
76 =head1 DESCRIPTION
77
78 This program takes a I<lazy formatted> LaTeX table from STDIN (typically piped
79 from Vim or emacs) and outputs a completely formatted table.
80
81 =head1 LAZY FORMAT
82
83 The first line must contain the L<LaTeX::Table> options (seperated by
84 semicolons C<;>) in the format C<optionname=value>. The
85 second line must contain the header, the following lines the data.
86 Columns are seperated by C<&>.
87
88 =head1 EXAMPLE
89
90
91 theme=NYC;label=test;position=htb
92 Header Col1 & Header Col2
93 Data Col1 & Data Col2
94
95 =head1 VIM
96
97 =over
98
99 =item 1. Select the text in C<VISUAL LINE> mode (C<shift+v>).
100
101 =item 2. Type C<!ltpretty>
102
103 =back
104
105 =head1 EMACS
106
107 =over
108
109 =item 1. Select the text
110
111 =item 2. Press C<alt+|>
112
113 =item 3. Now "Shell command on region" should appear. Type C<ltpretty>
114
115 =back
116
117 =head1 CONFIGURATION AND ENVIRONMENT
118
119 C<ltpretty> does not support configuration files or environment variables.
120
121 =head1 DEPENDENCIES
122
123 L<LaTeX::Table>
124
125 =head1 BUGS AND LIMITATIONS
126
127 Our I<lazy format> does not support multi-line headers. Just add the other
128 header lines afterwards. More importantly, it currently does not support
129 non-scalar L<LaTeX::Table> options like for example C<columns_like_header>.
130 A future version may add this functionality.
131
132 Please report any bugs or feature requests to
133 C<bug-latex-table@rt.cpan.org>, or through the web interface at
134 L<http://rt.cpan.org>.
135
136 =head1 AUTHOR
137
138 Markus Riester C<< <mriester@gmx.de> >>
139
140 =head1 LICENSE AND COPYRIGHT
141
142 Copyright (c) 2006-2009, Markus Riester C<< <mriester@gmx.de> >>.
143
144 This program is free software; you can redistribute it and/or
145 modify it under the same terms as Perl itself. See L<perlartistic>.
146
147 =head1 DISCLAIMER OF WARRANTY
148
149 BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
150 FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
151 OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
152 PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
153 EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
154 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
155 ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
156 YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
157 NECESSARY SERVICING, REPAIR, OR CORRECTION.
158
159 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
160 WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
161 REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
162 LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
163 OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
164 THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
165 RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
166 FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
167 SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
168 SUCH DAMAGES.
169
170 =cut
171
172 # vim: ft=perl sw=4 ts=4 expandtab
Binary diff not shown
0 #!/usr/bin/perl
1
2 use strict;
3 use warnings;
4
5 use LaTeX::Table;
6 use LaTeX::Encode;
7 use Number::Format qw(:subs);
8 use Data::Dumper;
9 use Text::CSV;
10
11 system('rm *.tex');
12
13 my $test_data = [
14 [ 'Gnat', 'per gram', '13.651' ],
15 [ '', 'each', '0.012' ],
16 [ 'Gnu', 'stuffed', '92.59' ],
17 [ 'Emu', 'stuffed', '33.33' ],
18 [ 'Armadillo', 'frozen', '8.99' ],
19 ];
20
21 my $test_data_large = [];
22
23 for my $i ( 1 .. 9 ) {
24 $test_data_large = [ @$test_data_large, @$test_data ];
25 }
26
27 my $table = LaTeX::Table->new(
28 { maincaption => 'Price List',
29 fontsize => 'large',
30 caption => '',
31 callback => sub {
32 my ( $row, $col, $value, $is_header ) = @_;
33 if ( $col == 2 && !$is_header ) {
34 $value = format_price( $value, 2, '' );
35 }
36 return $value;
37 },
38 }
39 );
40
41 my $themes = {
42 'Custom' => {
43 'HEADER_FONT_STYLE' => 'sc',
44 'HEADER_CENTERED' => 1,
45 'CAPTION_FONT_STYLE' => 'sc',
46 'VERTICAL_RULES' => [ 1, 2, 1 ],
47 'HORIZONTAL_RULES' => [ 1, 2, 0 ],
48 },
49 };
50
51 $table->set_custom_themes($themes);
52
53 foreach my $theme ( keys %{ $table->get_available_themes } ) {
54
55 my $test_header
56 = [ [ 'Item:2c', '' ], [ 'Animal', 'Description', 'Price' ] ];
57
58 if ( $theme eq 'Zurich' || $theme eq 'Meyrin' ) {
59 $test_header = [
60 [ 'Item:2c', '' ],
61 ['\cmidrule(r){1-2}'],
62 [ 'Animal', 'Description', 'Price' ]
63 ];
64 }
65
66 $table->set_maincaption("\\texttt{theme=$theme, type=std}");
67
68 if ($theme eq 'Muenchen') {
69 $table->set_fontfamily('sf');
70 }
71 else {
72 $table->set_fontfamily(0);
73 }
74 $table->set_filename("$theme.tex");
75 $table->set_position('!htb');
76 $table->set_caption_top(0);
77 $table->set_theme($theme);
78 $table->set_type('std');
79 $table->set_header($test_header);
80 $table->set_data($test_data);
81 #$table->set_width('0.9\textwidth');
82 $table->generate();
83
84 $table->set_type('ctable');
85 $table->set_maincaption("\\texttt{theme=$theme, type=ctable}");
86
87 $table->set_label("theme${theme}ctable");
88 $table->set_filename("${theme}ctable.tex");
89 $table->generate();
90 $table->set_label(0);
91
92 # warn Dumper $test_data;
93 $table->set_type('xtab');
94 $table->set_maincaption("\\texttt{theme=$theme, type=xtab}");
95 $table->set_position(0);
96
97 # $table->set_caption_top(1);
98 $table->set_filename("${theme}multipage.tex");
99 $table->set_xentrystretch(-0.1);
100 $table->set_header($test_header);
101 $table->set_data($test_data_large);
102 $table->set_caption_top(
103 '\setlength{\abovecaptionskip}{0pt}\setlength{\belowcaptionskip}{10pt}\topcaption'
104 );
105 $table->generate();
106 $table->set_filename("${theme}multipage2.tex");
107 $table->set_type('longtable');
108 $table->set_maincaption("\\texttt{theme=$theme, type=longtable}");
109 $table->generate();
110 }
111
112 open my $OUT, '>', 'examples.tex';
113 foreach my $line (<DATA>) {
114 print $OUT $line;
115 }
116
117 my $code = << 'EOC'
118 \subsection{Table width, tabular* environment}
119 \tref{tbl:width} demonstrates a fixed-width table in the \texttt{tabular*}
120 environment. Here, the space between the columns is filled with spaces.
121 \begin{verbatim}
122 $table = LaTeX::Table->new(
123 { header => $header,
124 data => $data,
125 width => '0.7\textwidth',
126 label => 'tbl:width',
127 caption => '\texttt{width}',
128 }
129 );
130 \end{verbatim}
131 EOC
132 ;
133 my $test_header = [ [ 'Animal', 'Description', 'Price' ] ];
134 $table = LaTeX::Table->new(
135 { header => $test_header,
136 data => $test_data,
137 label => 'tbl:width',
138 width => '0.7\textwidth',
139 caption => '\texttt{width}',
140 }
141 );
142 print ${OUT} $code . $table->generate_string;
143
144 $code = << 'EOC'
145 \subsection{Large Columns}
146 The next example is a small table with two larger columns.
147 \cpanmodule{LaTeX::Table} automatically sets the column to \texttt{p\{5cm\}} when a
148 cell in a column has more than 30 characters. \LaTeX~generates
149 \tref{tbl:paragraph}.
150
151 \begin{verbatim}
152 $table = LaTeX::Table->new(
153 { header => $header,
154 data => $data,
155 label => 'tbl:paragraph',
156 caption => 'LaTeX paragraph column attribute.',
157 }
158 );
159 \end{verbatim}
160 EOC
161 ;
162
163 my $header = [ [ 'Character', 'Fullname', 'Voice' ], ];
164 my $data = [
165 [ 'Homer', 'Homer Jay Simpson', 'Dan Castellaneta', ],
166 [ 'Marge', 'Marjorie Simpson (née Bouvier)', 'Julie Kavner', ],
167 [ 'Bart', 'Bartholomew Jojo Simpson', 'Nancy Cartwright', ],
168 [ 'Lisa', 'Elizabeth Marie Simpson', 'Yeardley Smith', ],
169 [ 'Maggie',
170 'Margaret Simpson',
171 'Elizabeth Taylor, Nancy Cartwright, James Earl Jones,'
172 . 'Yeardley Smith, Harry Shearer',
173 ],
174 ];
175 $table = LaTeX::Table->new(
176 { header => $header,
177 data => $data,
178 label => 'tbl:paragraph',
179 caption => 'LaTeX paragraph column attribute.',
180 }
181 );
182
183 print ${OUT} $code;
184
185 #$table->set_tabledef_strategy( { 'LONG_COL' => 'p{4cm}', 'IS_LONG' => 30 } );
186 print ${OUT} $table->generate_string;
187
188 $code = << 'EOC'
189 \subsubsection{\texttt{tabularx}}
190 We can use the \ctanpackage{tabularx} package to find better column widths than the
191 default 5cm. See \tref{tbl:tabularx} for the results.
192 \begin{verbatim}
193 $table = LaTeX::Table->new(
194 { header => $header,
195 data => $data,
196 width => '0.9\textwidth',
197 width_environment => 'tabularx',
198 label => 'tbl:tabularx',
199 caption => '\texttt{width\_environment=tabularx}.',
200 }
201 );
202 \end{verbatim}
203 EOC
204 ;
205 $table->set_label('tbl:tabularx');
206 $table->set_caption('\texttt{width\_environment=tabularx}.');
207
208 $table->set_width('0.9\textwidth');
209 $table->set_width_environment('tabularx');
210 print ${OUT} $code . $table->generate_string;
211
212 $code = << 'EOC'
213 \subsubsection{\texttt{tabulary}}
214 A third option is to use the \ctanpackage{tabulary} package. See \tref{tbl:tabulary}.
215 \begin{verbatim}
216 $table = LaTeX::Table->new(
217 { header => $header,
218 data => $data,
219 width => '0.9\textwidth',
220 width_environment => 'tabulary',
221 label => 'tbl:tabulary',
222 caption => '\texttt{width\_environment=tabulary}.',
223 }
224 );
225 \end{verbatim}
226 EOC
227 ;
228 $table->set_label('tbl:tabulary');
229 $table->set_caption('\texttt{width\_environment=tabulary}.');
230 $table->set_width_environment('tabulary');
231
232 print ${OUT} $code . $table->generate_string;
233
234 $code = << 'EOC'
235 \subsection{Rotate tables}
236 \tref{tbl:sideways} demonstrates the \ltoption{sideways} option. Requires the
237 \ctanpackage{rotating} package.
238 \begin{verbatim}
239 $table = LaTeX::Table->new(
240 { header => $header,
241 data => $data,
242 width => '0.9\textwidth',
243 width_environment
244 => 'tabularx',
245 sideways => 1,
246 label => 'tbl:sideways',
247 caption => '\texttt{width\_environment=tabularx, sideways}.',
248 }
249 );
250 \end{verbatim}
251 EOC
252 ;
253
254 $table->set_sideways(1);
255 $table->set_caption('\texttt{width\_environment=tabularx, sideways}.');
256 $table->set_label('tbl:sideways');
257
258 print ${OUT} $code . $table->generate_string;
259
260 $code = << 'EOC'
261 \subsection{Resize tables}
262 In Tables \ref{tbl:resizebox1} and \ref{tbl:resizebox2}, the
263 \ltoption{resizebox} option was used to get the desired width (and height in
264 the second example). Requires the \ctanpackage{graphicx} package.
265 \begin{verbatim}
266 $table = LaTeX::Table->new(
267 { header => $header,
268 data => $data,
269 resizebox => [ '0.6\textwidth' ],
270 label => 'tbl:resizebox1',
271 caption => '\texttt{resizebox}, Example 1',
272 }
273 );
274
275 $table->set_resizebox([ '300pt', '120pt' ]);
276 \end{verbatim}
277 EOC
278 ;
279
280 $table->set_sideways(0);
281 $table->set_label('tbl:resizebox1');
282 $table->set_resizebox( ['0.6\textwidth'] );
283 $table->set_caption('\texttt{resizebox}, Example 1');
284
285 print ${OUT} $code . $table->generate_string;
286
287 $table->set_label('tbl:resizebox2');
288 $table->set_resizebox( [ '300pt', '120pt' ] );
289 $table->set_caption('scaled to a size of 300pt x 120pt');
290 $table->set_caption('\texttt{resizebox}, Example 2');
291
292 print ${OUT} $table->generate_string;
293
294 $code = << 'EOC'
295 \subsection{Callback functions}
296 Callback functions are an easy way of formatting the cells. Note that the
297 prices for Gnat are rounded in the following tables.
298 \begin{verbatim}
299 my $table = LaTeX::Table->new(
300 {
301 filename => 'prices.tex',
302 maincaption => 'Price List',
303 caption => 'Try our special offer today!',
304 label => 'tbl:prices',
305 header => $header,
306 data => $data,
307 callback => sub {
308 my ($row, $col, $value, $is_header ) = @_;
309 if ($col == 2 && $!is_header) {
310 $value = format_price($value, 2, '');
311 }
312 return $value;
313 },
314 });
315 \end{verbatim}
316 EOC
317 ;
318
319 print $OUT $code;
320
321 $header = [
322 [ 'Item:2c', '' ],
323 ['\cmidrule(r){1-2}'],
324 [ 'Animal', 'Description', 'Price' ]
325 ];
326
327 $data = [
328 [ 'Gnat', 'per gram', '13.651' ],
329 [ '', 'each', '0.012' ],
330 [ 'Gnu', 'stuffed', '92.59' ],
331 [ 'Emu', 'stuffed', '33.33' ],
332 [ 'Armadillo', 'frozen', '8.99' ],
333 ];
334
335 $table = LaTeX::Table->new(
336 { filename => 'prices.tex',
337 caption => '\texttt{caption\_top}, Example 1',
338 caption_top => 1,
339 label => 'table:pricestop',
340 header => $header,
341 data => $data,
342 callback => sub {
343 my ( $row, $col, $value, $is_header ) = @_;
344 if ($is_header) {
345 $value = uc $value;
346 }
347 elsif ( $col == 2 && !$is_header ) {
348 $value = format_price( $value, 2, '' );
349 }
350 return $value;
351 },
352 }
353 );
354
355 $code = << 'EOT';
356 \subsection{Captions}
357 \subsubsection{Placement}
358 Tables can be placed on top of the tables with \ltoption{caption\_top => 1}. See
359 \tref{table:pricestop}. Note that the standard \LaTeX~macros are optimized for
360 bottom captions. Use something like
361 \begin{verbatim}
362 \usepackage[tableposition=top]{caption}
363 \end{verbatim}
364 to fix the spacing. Alternatively, you could fix the spacing by yourself by
365 providing your own command(s) (\tref{table:pricestop2}):
366 \begin{verbatim}
367 $table->set_caption_top(
368 '\setlength{\abovecaptionskip}{0pt}' .
369 '\setlength{\belowcaptionskip}{10pt}' .
370 \caption'
371 );
372 \end{verbatim}
373 EOT
374
375 print $OUT $code . $table->generate_string();
376 $table->set_caption_top(
377 '\setlength{\abovecaptionskip}{0pt}\setlength{\belowcaptionskip}{10pt}\caption'
378 );
379 $table->set_label('table:pricestop2');
380 $table->set_caption('\texttt{caption\_top}, Example 2');
381
382 print $OUT $table->generate_string();
383
384 $code = << 'EOT';
385 \subsection{Multicolumns}
386 If you want tables with vertical lines (are you sure?) you should use our
387 shortcut to generate multicolumns. These shortcuts are not only much less
388 typing work, but they also automatically add the vertical lines, see
389 \tref{tbl:mc}.
390 \begin{verbatim}
391 $header = [ [ 'A:3c' ],
392 [ 'A:2c', 'B' ],
393 ['A', 'B', 'C' ], ];
394
395 $data = [ [ '1', 'w', 'x' ],
396 [ '2', 'c:2c' ], ];
397
398 $table = LaTeX::Table->new(
399 { header => $header,
400 data => $data,
401 theme => 'Dresden',
402 label => 'tbl:mc',
403 caption => 'Multicolumns.',
404 }
405 );
406 \end{verbatim}
407 EOT
408
409 $header = [ ['A:3c'], [ 'A:2c', 'B' ], [ 'A', 'B', 'C' ], ];
410 $data = [ [ '1', 'w', 'x' ], [ '2', 'c:2c' ], ];
411
412 $table = LaTeX::Table->new(
413 { environment => 1,
414 header => $header,
415 data => $data,
416 label => 'tbl:mc',
417 caption => 'Multicolumns.',
418 theme => 'Dresden',
419 }
420 );
421
422 print $OUT $code . $table->generate_string();
423
424
425 $code = << 'EOT';
426 \subsection{Headers}
427 If you don't need headers, just leave them undefined (see
428 \tref{tbl:noheader}). If you want that the first column looks like a header,
429 you can define this with the \ltoption{columns\_like\_header} option
430 (\tref{table:collikeheader} and \tref{table:collikeheader2}). You
431 can also rotate the header columns by 90 degrees
432 (\tref{table:headersideways}) with \ltoption{header\_sideways}. If you do
433 not want to rotate all header cells, use a callback function instead
434 (\tref{table:headersideways2}).
435 \begin{verbatim}
436 $table = LaTeX::Table->new(
437 {
438 data => $data,
439 label => 'tbl:noheader',
440 caption => 'Table without header.',
441 });
442 \end{verbatim}
443 EOT
444
445 $data = [
446 [ 'Gnat', 'per gram', '13.651' ],
447 [ '', 'each', '0.012' ],
448 [ 'Gnu', 'stuffed', '92.59' ],
449 [ 'Emu', 'stuffed', '33.33' ],
450 [ 'Armadillo', 'frozen', '8.99' ],
451 ];
452
453 $table = LaTeX::Table->new(
454 { caption => 'Table without header.',
455 label => 'tbl:noheader',
456 data => $data,
457 }
458 );
459
460
461 print $OUT $code . $table->generate_string();
462
463 $table->set_theme('NYC2');
464 $table->set_columns_like_header( [0] );
465 $table->set_label('table:collikeheader');
466 $table->set_caption('\texttt{columns\_like\_header}, Example 1: A transposed table.');
467
468 print $OUT $table->generate_string();
469
470 $table->set_label('table:collikeheader2');
471 $table->set_caption('\texttt{columns\_like\_header}, Example 2.');
472 $table->set_header($header);
473
474 print $OUT $table->generate_string();
475
476 $table->set_theme('NYC');
477 $header
478 = [ [ 'Time', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday' ] ];
479
480 $data = [
481 [ '9.00', '', '', '', '', '', ],
482 [ '10.00', '', '', '', '', '', ],
483 [ '11.00', '', '', '', '', '', ],
484 [ '12.00', '', '', '', '', '', ],
485 ];
486
487 $table = LaTeX::Table->new(
488 { header => $header,
489 data => $data,
490 header_sideways => 1,
491 left => 1,
492 theme => 'NYC',
493 label => 'table:headersideways',
494 caption => '\texttt{header\_sideways, left}',
495 }
496 );
497
498 print $OUT $table->generate_string();
499
500 $table = LaTeX::Table->new(
501 { header => $header,
502 data => $data,
503 label => 'table:headersideways2',
504 caption => '\texttt{callback, right}',
505 header_sideways => 0,
506 right => 1,
507 callback => sub {
508 my ( $row, $col, $value, $is_header ) = @_;
509 if ( $col != 0 && $is_header ) {
510 $value = '\begin{sideways}' . $value . '\end{sideways}';
511 }
512 return $value;
513 },
514 theme => 'NYC',
515 }
516 );
517
518 print $OUT $table->generate_string();
519
520 $code = << 'EOT';
521 \subsection{CSV Files}
522 For importing CSV files, we can use the CPAN module \cpanmodule{Text::CSV}:
523 \begin{verbatim}
524 my $csv = Text::CSV->new(
525 { binary => 1,
526 sep_char => q{,},
527 allow_whitespace => 1
528 }
529 );
530
531 open my $IN, '<', 'imdbtop40.dat';
532
533 my $line_number = 0;
534 while ( my $line = <$IN> ) {
535 chomp $line;
536 my $status = $csv->parse($line);
537 if ( $line_number == 0 ) {
538 $header = [ [ $csv->fields() ] ];
539 }
540 else {
541 push @{$data}, [ $csv->fields() ];
542 }
543 $line_number++;
544 }
545 close $IN;
546
547 $table = LaTeX::Table->new(
548 { header => $header,
549 data => $data,
550 type => 'xtab',
551 sideways => 1,
552 tabletail => q{},
553 label => 'tbl:xtab',
554 caption => '\texttt{type=xtab}',
555 caption_top => 1,
556 }
557 );
558 \end{verbatim}
559 See \tref{tbl:xtab}, which uses the \ctanpackage{xtab} package for spanning across
560 multiple pages. You can also use the \ctanpackage{longtable} package here.
561 This package can be used together with the \ctanpackage{ltxtable} package to
562 define a table width. Here, you have to generate a \textit{file} and then load the
563 file with the \texttt{LTXtable} command. See \tref{tbl:longtable}.
564 \begin{verbatim}
565 $table = LaTeX::Table->new(
566 { header => $header,
567 data => $data,
568 type => 'longtable',
569 tabletail => q{},
570 label => 'tbl:longtable',
571 caption => '\texttt{type=longtable}',
572 caption_top => 1,
573 center => 0,
574 # we don't define a width here!
575 width_environment => 'tabularx',
576 filename => 'longtable.tex'
577 }
578 );
579
580 %now in LaTeX:
581 \begin{center}
582 \LTXtable{0.8\textwidth}{longtable}
583 \end{center}
584
585 \end{verbatim}
586 EOT
587 my $line_number = 0;
588
589 my $csv = Text::CSV->new(
590 { binary => 1,
591 sep_char => q{,},
592 allow_whitespace => 1
593 }
594 );
595
596 @{$data} = ();
597
598 open my $IN, '<', 'imdbtop40.dat';
599 while ( my $line = <$IN> ) {
600 chomp $line;
601 my $status = $csv->parse($line);
602 if ( $line_number == 0 ) {
603 $header = [ [ $csv->fields() ] ];
604 }
605 else {
606 push @{$data}, [ $csv->fields() ];
607 }
608 $line_number++;
609 }
610 close $IN;
611
612 $table = LaTeX::Table->new(
613 { header => $header,
614 data => $data,
615 type => 'xtab',
616 sideways => 1,
617 tabletail => q{ },
618 label => 'tbl:xtab',
619 caption => '\texttt{type=xtab}',
620 caption_top =>
621 '\setlength{\abovecaptionskip}{0pt}\setlength{\belowcaptionskip}{10pt}\topcaption',
622 }
623 );
624 print $OUT $code . $table->generate_string();
625
626 $table = LaTeX::Table->new(
627 { header => $header,
628 data => $data,
629 type => 'longtable',
630 tabletail => q{},
631 label => 'tbl:longtable',
632 caption => '\texttt{type=longtable}',
633 caption_top => 1,
634 center => 0,
635 # we don't define a width here!
636 width_environment => 'tabularx',
637 filename => 'longtable.tex',
638 });
639
640 print $table->generate();
641
642 $code = << 'EOT';
643 \begin{center}
644 \LTXtable{0.8\textwidth}{longtable}
645 \end{center}
646
647 \subsection{Automatic column definitions}
648 We can easily provide regular expressions that define the alignment of
649 columns. See \tref{tbl:coldef_strategy}.
650 \begin{verbatim}
651 $table = LaTeX::Table->new(
652 { header => [ [ 'Website', 'URL' ] ],
653 data => [
654 [ 'Slashdot', 'http://www.slashdot.org' ],
655 [ 'Perlmonks', 'http://www.perlmonks.org' ],
656 [ 'Google', 'http://www.google.com' ],
657 ],
658 coldef_strategy => {
659 URL => qr{ \A \s* http }xms,
660 URL_COL => '>{\ttfamily}l',
661 },
662 label => 'tbl:coldef_strategy',
663 caption => '\texttt{coldef\_strategy}',
664 }
665 );
666 \end{verbatim}
667 EOT
668
669 $table = LaTeX::Table->new(
670 { header => [ [ 'Website', 'URL' ] ],
671 data => [
672 [ 'Slashdot', 'http://www.slashdot.org' ],
673 [ 'Perlmonks', ' http://www.perlmonks.org' ],
674 [ 'Google', 'http://www.google.com' ],
675 ],
676 coldef_strategy => {
677 URL => qr{ \A \s* http }xms,
678 URL_COL => '>{\ttfamily}l',
679 },
680 label => 'tbl:coldef_strategy',
681 caption => '\texttt{coldef\_strategy}',
682 }
683 );
684
685 print $OUT $code . $table->generate_string();
686
687 $code = << 'EOT';
688 \subsection{Continued Tables}
689 As alternative to multi-page tables, we can also split tables. The
690 \ltoption{continued} option then decrements the table counter and adds the
691 \ltoption{continuedmsg} (default is `(continued)') to the caption. See
692 \tref{tbl:coldef_strategy}. That even works with \ltoption{xtab} tables.
693 \begin{verbatim}
694 $table = LaTeX::Table->new(
695 { header => [ [ 'Website', 'URL' ] ],
696 data => [
697 [ 'CPAN', 'http://www.cpan.org' ],
698 [ 'Amazon', 'http://www.amazon.com' ],
699 ],
700 coldef_strategy => {
701 URL => qr{ \A \s* http }xms,
702 URL_COL => '>{\ttfamily}l',
703 },
704 continued => 1,
705 label => 'tbl:continued',
706 caption => '\texttt{continued}',
707 }
708 );
709 \end{verbatim}
710 EOT
711 $table = LaTeX::Table->new(
712 { header => [ [ 'Website', 'URL' ] ],
713 data => [
714 [ 'CPAN', 'http://www.cpan.org' ],
715 [ 'Amazon', 'http://www.amazon.com' ],
716 ],
717 coldef_strategy => {
718 URL => qr{ \A \s* http }xms,
719 URL_COL => '>{\ttfamily}l',
720 },
721 continued => 1,
722 label => 'tbl:continued',
723 caption => '\texttt{continued}',
724 }
725 );
726
727 print $OUT $code . $table->generate_string();
728
729
730 $code = << 'EOT';
731 \subsection{Ctable Package}
732 The \ctanpackage{ctable} package makes it easy to add footnotes. See
733 \tref{tbl:websitectable}.
734 \begin{verbatim}
735 $table->set_type('ctable');
736 $table->set_foottable('\tnote{footnotes are placed under the table}');
737 \end{verbatim}
738 EOT
739
740 $table->set_label('tbl:websitectable');
741 $table->set_caption('\texttt{coldef\_strategy, type=ctable, foottable, continued}.');
742 $table->set_type('ctable');
743 $table->set_foottable('\tnote{footnotes are placed under the table}');
744 $table->set_data(
745 [
746 [ 'Slashdot\tmark', 'http://www.slashdot.org' ],
747 [ 'Perlmonks', 'http://www.perlmonks.org' ],
748 [ 'Google', 'http://www.google.com' ],
749 ]);
750
751 print $OUT $code . $table->generate_string();
752
753
754 $code = << 'EOT';
755 \subsection{Multicols}
756 In a twocolumn or multicols document, we use this starred version for
757 \tref{table:websitectablestar}:
758
759 \begin{multicols}{2}
760 \begin{verbatim}
761 $table->set_star(1);
762 \end{verbatim}
763 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
764 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
765 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
766 bla bla bla bla bla bla
767
768 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
769 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
770 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
771 bla bla bla bla bla bla
772
773 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
774 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
775 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
776 bla bla bla bla bla bla
777 EOT
778
779 $table->set_star(1);
780 $table->set_continued(0);
781 $table->set_position('htbp');
782 $table->set_label('table:websitectablestar');
783 $table->set_caption('\texttt{coldef\_strategy, type=ctable, foottable, star}.');
784 print $OUT $code . $table->generate_string();
785
786 $code = << 'EOT';
787 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
788 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
789 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
790 bla bla bla bla bla bla
791
792 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
793 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
794 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
795 bla bla bla bla bla bla
796
797 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
798 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
799 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
800 bla bla bla bla bla bla
801 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
802 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
803 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
804 bla bla bla bla bla bla
805
806 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
807 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
808 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
809 bla bla bla bla bla bla
810
811 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
812 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
813 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
814 bla bla bla bla bla bla
815 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
816 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
817 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
818 bla bla bla bla bla bla
819
820 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
821 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
822 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
823 bla bla bla bla bla bla
824
825 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
826 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
827 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
828 bla bla bla bla bla bla
829 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
830 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
831 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
832 bla bla bla bla bla bla
833
834 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
835 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
836 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
837 bla bla bla bla bla bla
838
839 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
840 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
841 bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
842 bla bla bla bla bla bla
843 EOT
844
845 print $OUT $code . "\n\\end{multicols}\n";
846
847 $code = << 'EOT';
848 \section{Customize \cpanmodule{LaTeX::Table}}
849
850 This module tries hard to produce perfect results with as less provided
851 options as possible. However, typesetting tables is a complex topic and
852 therefore almost everything in \cpanmodule{LaTeX::Table} is configurable.
853
854 \subsection{Custom Themes}\label{sec:customthemes}
855
856 \tref{table:customtheme1} displays our example table with the \textit{NYC}
857 theme, which is meant for presentations (with LaTeX Beamer for example). You
858 can change the theme by copying it, changing it and then storing it in
859 \ltoption{custom\_themes} (\tref{table:customtheme2}). You can also add the
860 theme to the predfined themes by creating a themes module. See
861 \cpanmodule{LaTeX::Table::Themes::ThemeI} how to do that.
862 \begin{verbatim}
863 my $nyc_theme = $table->get_available_themes->{'NYC'};
864 $nyc_theme->{'DEFINE_COLORS'} =
865 '\definecolor{latextablegreen}{RGB}{93,127,114}';
866 $nyc_theme->{'HEADER_BG_COLOR'} = 'latextablegreen';
867 $nyc_theme->{'DATA_BG_COLOR_ODD'} = 'latextablegreen!25';
868 $nyc_theme->{'DATA_BG_COLOR_EVEN'} = 'latextablegreen!10';
869
870 $table->set_custom_themes({ CENTRALPARK => $nyc_theme });
871 $table->set_theme('CENTRALPARK');
872 \end{verbatim}
873 EOT
874
875 $header = [ [ 'Item:2c', '' ], [ 'Animal', 'Description', 'Price' ] ];
876
877 $data = [
878 [ 'Gnat', 'per gram', '13.651' ],
879 [ '', 'each', '0.012' ],
880 [ 'Gnu', 'stuffed', '92.59' ],
881 [ 'Emu', 'stuffed', '33.33' ],
882 [ 'Armadillo', 'frozen', '8.99' ],
883 ];
884
885 $table = LaTeX::Table->new(
886 { filename => 'prices.tex',
887 caption => '\texttt{custom\_themes}, Example 1',
888 label => 'table:customtheme1',
889 header => $header,
890 data => $data,
891 theme => 'NYC',
892 callback => sub {
893 my ( $row, $col, $value, $is_header ) = @_;
894 if ( $col == 2 && !$is_header ) {
895 $value = format_price( $value, 2, '' );
896 }
897 return $value;
898 },
899 }
900 );
901
902 print $OUT $code . $table->generate_string();
903
904 my $nyc_theme = $table->get_available_themes->{'NYC'};
905 $nyc_theme->{'DEFINE_COLORS'}
906 = '\definecolor{latextablegreen}{RGB}{93,127,114}';
907 $nyc_theme->{'HEADER_BG_COLOR'} = 'latextablegreen';
908 $nyc_theme->{'DATA_BG_COLOR_ODD'} = 'latextablegreen!25';
909 $nyc_theme->{'DATA_BG_COLOR_EVEN'} = 'latextablegreen!10';
910 $nyc_theme->{'EXTRA_ROW_HEIGHT'} = '1pt';
911
912 $table->set_custom_themes( { CENTRALPARK => $nyc_theme } );
913 $table->set_theme('CENTRALPARK');
914 $table->set_label('table:customtheme2');
915 $table->set_caption('\texttt{custom\_themes}, Example 2');
916
917 print $OUT $table->generate_string();
918
919 $code = << 'EOT';
920 \subsection{Custom Templates}\label{sec:customtemplates}
921
922 \cpanmodule{LaTeX::Table} ships with some very flexible and powerful
923 templates. Templates are a convenient way of generating the LaTeX code out of
924 the user options and data. Internally, the \cpanmodule{Template} Toolkit
925 available from CPAN is used. It is possible to change the standard templates
926 (each table \ltoption{type} has its own template) with the
927 \ltoption{custom\_template} option. For example, the \LaTeX~styles of some
928 scientific journals provide their own table commands, here the one from the
929 Bioinformatics journal:
930
931 \begin{verbatim}
932 \begin{table}[!t]
933 \processtable{This is table caption\label{Tab:01}}
934 {\begin{tabular}{llll}
935 \toprule
936 head1 & head2 & head3 & head4 \\
937 \midrule
938 row1 & row1 & row1 & row1 \\
939 row2 & row2 & row2 & row2 \\
940 row3 & row3 & row3 & row3 \\
941 row4 & row4 & row4 & row4 \\
942 \botrule
943 \end{tabular}}{This is a footnote}
944 \end{table}
945 \end{verbatim}
946 A very basic template for this would be:
947 {\footnotesize
948 \begin{verbatim}
949 [% IF ENVIRONMENT %]
950 \begin{[% ENVIRONMENT %][% IF STAR %]*[% END %]}[% IF POSITION %][[% POSITION %]]
951 [% END %][% END %]
952 \processtable{[% IF CAPTION %][% CAPTION %][% END %][% IF LABEL %]\label{[% LABEL %]}[% END %]}
953 {\begin{[% TABULAR_ENVIRONMENT %]}{[% COLDEF %]}
954 [% HEADER_CODE %][% DATA_CODE %]\end{[% TABULAR_ENVIRONMENT %]}}{[% FOOTTABLE %]}
955 [% IF ENVIRONMENT %]\end{table}[% END %]
956 \end{verbatim}}
957 \noindent Now we have to define a the theme that is responsible for the rules (see
958 \ref{sec:customthemes}):
959 \begin{verbatim}
960 'Oxford' => {
961 'STUB_ALIGN' => q{l},
962 'VERTICAL_RULES' => [ 0, 0, 0 ],
963 'HORIZONTAL_RULES' => [ 1, 1, 0 ],
964 'RULES_CMD' => [ '\toprule', '\midrule', '\midrule', '\botrule' ],
965 }
966 \end{verbatim}
967 Finally we can typeset tables for the Bioinformatics journal:
968 \begin{verbatim}
969 $table = LaTeX::Table->new(
970 {
971 caption => 'This is table caption',
972 label => 'Tab:01',
973 foottable => 'This is a footnote',
974 position => '!t',
975 header => $test_header,
976 data => $test_data,
977 theme => 'Oxford',
978 custom_template => $custom_template,
979 }
980 );
981 \end{verbatim}
982 If you think your custom template might be useful for others, please
983 contribute it!
984 EOT
985 ;
986
987 print ${OUT}
988 "$code\\section{Version}\\small{Generated with LaTeX::Table Version $LaTeX::Table::VERSION}\n";
989
990 $code = << 'EOT';
991 \clearpage\begin{appendix}
992 \section{Header/Data}
993 \subsection{Simpsons Table}
994 \begin{verbatim}
995 my $header = [ [ 'Character', 'Fullname', 'Voice' ], ];
996 my $data = [
997 [ 'Homer', 'Homer Jay Simpson', 'Dan Castellaneta' ],
998 [ 'Marge', 'Marjorie Simpson', 'Julie Kavner' ],
999 [ 'Bart', 'Bartholomew Jojo Simpson', 'Nancy Cartwright' ],
1000 [ 'Lisa', 'Elizabeth Marie Simpson', 'Yeardley Smith' ],
1001 [ 'Maggie', 'Margaret Simpson',
1002 'Elizabeth Taylor, Nancy Cartwright, James Earl Jones,'
1003 . 'Yeardley Smith, Harry Shearer' ],
1004 ];
1005 \end{verbatim}
1006
1007 \subsection{Animal Table}
1008
1009 \begin{verbatim}
1010 my $header = [
1011 [ 'Item:2c', '' ],
1012 [ '\cmidrule(r){1-2}'],
1013 [ 'Animal', 'Description', 'Price' ]
1014 ];
1015
1016 my $data = [
1017 [ 'Gnat', 'per gram', '13.651' ],
1018 [ '', 'each', '0.012' ],
1019 [ 'Gnu', 'stuffed', '92.59' ],
1020 [ 'Emu', 'stuffed', '33.33' ],
1021 [ 'Armadillo', 'frozen', '8.99' ],
1022 ];
1023 \end{verbatim}
1024
1025 \section{Themes}
1026 EOT
1027 ;
1028 print $OUT $code;
1029
1030 $table = LaTeX::Table->new();
1031
1032 my %section = ( std => '',
1033 ctable => 'ctable',
1034 longtable => 'multipage2',
1035 xtab => 'multipage',);
1036
1037 for my $sect (qw(std ctable xtab longtable)) {
1038
1039 print $OUT "\\subsection{Type $sect}\n";
1040 for my $theme ( sort keys %{ $table->get_available_themes } ) {
1041 print $OUT "\\input{$theme$section{$sect}.tex}\n";
1042 if ($sect eq "xtab") {
1043 print $OUT "\\clearpage \n";
1044 }
1045 }
1046 print $OUT "\\clearpage \n";
1047 }
1048 print $OUT '\end{appendix}\end{document}' . "\n";
1049 close $OUT;
1050
1051 __DATA__
1052 \documentclass[11pt]{article}
1053 \usepackage{layouts}
1054
1055 \setlength{\textheight}{8.0in}
1056 \setlength{\textwidth}{6.0in}
1057 \setlength{\oddsidemargin}{0.25in}
1058 \setlength{\evensidemargin}{0.25in}
1059 \setlength{\marginparwidth}{0.6in}
1060 \setlength{\parskip}{5pt}
1061 \setcounter{secnumdepth}{4}
1062 \setcounter{tocdepth}{4}
1063
1064 \setlength{\columnsep}{30pt}
1065
1066 \setcounter{topnumber}{2}
1067 \setcounter{bottomnumber}{2}
1068 \setcounter{totalnumber}{4}
1069 \renewcommand{\topfraction}{0.9}
1070 \renewcommand{\bottomfraction}{0.6}
1071 \renewcommand{\textfraction}{0.1}
1072
1073
1074 %\newlength{\figrulesep}
1075 %\setlength{\figrulesep}{0.5\textfloatsep}
1076 %
1077 %\newcommand{\topfigrule}{\vspace*{-1pt}%
1078 % \noindent\rule[-\figrulesep]{\columnwidth}{1pt}}
1079 %
1080 %\newcommand{\botfigrule}{\vspace*{-2pt}%
1081 % \noindent\rule[\figrulesep]{\columnwidth}{2pt}}
1082
1083 \makeatletter
1084
1085 \renewcommand{\subsubsection}{\@startsection%
1086 {subsubsection}%
1087 {3}%
1088 {0mm}%
1089 {-\baselineskip}%
1090 {0.5\baselineskip}%
1091 {\large\itshape}}
1092
1093
1094 \newcommand{\fref}[1]{Figure~\ref{#1}}
1095 \newcommand{\tref}[1]{Table~\ref{#1}}
1096 \newcommand{\T}{\texttt{true}}
1097 \newcommand{\F}{\texttt{false}}
1098 \newcommand{\TF}{\textit{true/false}}
1099
1100
1101 %%%% the \meta command
1102 \begingroup
1103 \obeyspaces%
1104 \catcode`\^^M\active%
1105 \gdef\meta{\begingroup\obeyspaces\catcode`\^^M\active%
1106 \let^^M\do@space\let \do@space%
1107 \def\-{\egroup\discretionary{-}{}{}\hbox\bgroup\it}%
1108 \m@ta}%
1109 \endgroup
1110 \def\m@ta#1{\leavevmode\hbox\bgroup$\langle$\it#1\/$\rangle$\egroup
1111 \endgroup}
1112 \def\do@space{\egroup\space
1113 \hbox\bgroup\it\futurelet\next\sp@ce}
1114 \def\sp@ce{\ifx\next\do@space\expandafter\sp@@ce\fi}
1115 \def\sp@@ce#1{\futurelet\next\sp@ce}
1116
1117 \newcommand{\marg}[1]{\texttt{\{}\meta{#1}\texttt{\}}}
1118
1119 \newcommand{\file}[1]{\textsf{#1}}
1120 \newcommand{\ltoption}[1]{\texttt{#1}}
1121 \newcommand{\ctanpackage}[1]{\file{#1}}
1122 \newcommand{\cpanmodule}[1]{\file{#1}}
1123
1124 \providecommand{\indexfill}{}
1125 \providecommand{\sindexfill}{}
1126 \providecommand{\ssindexfill}{}
1127 \providecommand{\otherindexspace}[1]{}
1128 \providecommand{\alphaindexspace}[1]{\indexspace{\bfseries #1}}
1129
1130 %%% \setlength{\parindent}{-4em}
1131 \makeatother
1132 \usepackage{url}
1133 \usepackage{ctable}
1134 \usepackage{graphics, graphicx}
1135 \usepackage{xtab}
1136 \usepackage{lscape}
1137 \usepackage{booktabs}
1138 \usepackage{rotating}
1139 \usepackage{tabularx}
1140 \usepackage{tabulary}
1141 \usepackage{listings}
1142 \usepackage{longtable}
1143 %\usepackage{color}
1144 \usepackage{colortbl}
1145 \usepackage{xcolor}
1146 \usepackage{graphicx}
1147 \usepackage{ltxtable}
1148 \usepackage{multicol}
1149 \usepackage{array}% in the preamble
1150 %\usepackage[tableposition=top]{caption}
1151 \title{LaTeX::Table}
1152 \date{\today}
1153 \author{Markus Riester}
1154 \makeindex
1155 \begin{document}
1156 \bibliographystyle{alpha}
1157 \pagenumbering{roman}
1158 \maketitle
1159 \begin{abstract}
1160
1161 \file{LaTeX::Table} is a Perl module that provides functionality for an
1162 intuitive and easy generation of LaTeX tables. It ships with some predefined
1163 good looking table styles. This module supports multipage tables via the
1164 \texttt{xtab} and the \texttt{longtable} package and publication quality
1165 tables with the \texttt{booktabs} package. It also supports the
1166 \texttt{tabularx} and \texttt{tabulary} packages for nicer fixed-width tables.
1167 Furthermore, it supports the \texttt{colortbl} package for colored tables
1168 optimized for presentations.
1169
1170 \end{abstract}
1171 \tableofcontents
1172 \listoftables
1173 \clearpage
1174 \pagenumbering{arabic}
1175
1176 \section{Installation}
1177 You can install this software with the \texttt{cpan} command.
1178
1179 \begin{verbatim}
1180 $ cpan LaTeX::Table
1181 \end{verbatim}
1182 Alternatively, download \cpanmodule{LaTeX::Table} directly from
1183 \url{http://search.cpan.org/dist/LaTeX-Table/} and install in manually:
1184 \begin{verbatim}
1185 $ tar xvfz LaTeX-Table-VERSION.tar.gz
1186 $ perl Build.PL
1187 $ ./Build test
1188 $ ./Build install
1189 \end{verbatim}
1190
1191 \section{Examples}
1192
0 Rank,Rating,Title,Year,Votes
1 1. ,9.1,"The Shawshank Redemption",1994,403610
2 2. ,9.1,"The Godfather",1972,338496
3 3. ,9.0,"The Godfather: Part II",1974,195253
4 4. ,8.9,"Buono, il brutto, il cattivo., Il",1966,117494
5 5. ,8.9,"The Dark Knight",2008,340243
6 6. ,8.9,"Pulp Fiction",1994,333085
7 7. ,8.8,"Schindler's List",1993,220503
8 8. ,8.8,"One Flew Over the Cuckoo's Nest",1975,168842
9 9. ,8.8,"12 Angry Men",1957,84726
10 10.,8.8,"Star Wars: Episode V - The Empire Strikes Back",1980,229894
11 11.,8.8,"Casablanca",1942,139763
12 12.,8.8,"Star Wars",1977,271586
13 13.,8.8,"Shichinin no samurai",1954,79374
14 14.,8.8,"The Lord of the Rings: The Return of the King",2003,294259
15 15.,8.7,"Goodfellas",1990,182825
16 16.,8.7,"Rear Window",1954,95538
17 17.,8.7,"Cidade de Deus",2002,124546
18 18.,8.7,"Raiders of the Lost Ark",1981,205298
19 19.,8.7,"C'era una volta il West",1968,56185
20 20.,8.7,"The Lord of the Rings: The Fellowship of the Ring",2001,322699
21 21.,8.7,"The Usual Suspects",1994,221641
22 22.,8.7,"Fight Club",1999,301078
23 23.,8.7,"Psycho",1960,115936
24 24.,8.6,"The Silence of the Lambs",1991,198677
25 25.,8.6,"Sunset Blvd.",1950,42280
26 26.,8.6,"Dr. Strangelove or: How I Learned to Stop Worrying and Love the Bomb",1964,131289
27 27.,8.6,"Memento",2000,217339
28 28.,8.6,"North by Northwest",1959,76221
29 29.,8.6,"Citizen Kane",1941,117600
30 30.,8.6,"The Matrix",1999,310491
31 31.,8.6,"It's a Wonderful Life",1946,84643
32 32.,8.6,"The Lord of the Rings: The Two Towers",2002, 269196
33 33.,8.6,"Se7en",1995,220400
34 34.,8.6,"Slumdog Millionaire",2008, 50475
35 35.,8.5,"Leon",1994,154149
36 36.,8.5,"Apocalypse Now",1979,142659
37 37.,8.5,"American Beauty",1999,241532
38 38.,8.5,"Taxi Driver",1976,122785
39 39.,8.5,"WALL-E",2008,114271
40 40.,8.5,"Lawrence of Arabia",1962,66188
0 #############################################################################
1 # $Author: markus $
2 # $Date: 2009-02-03 17:09:45 +0100 (Tue, 03 Feb 2009) $
3 # $Revision: 1298 $
4 #############################################################################
5
6 package LaTeX::Table::Themes::Beamer;
7 use Moose;
8
9 with 'LaTeX::Table::Themes::ThemeI';
10
11 use version;
12 our ($VERSION) = '$Revision: 1298 $' =~ m{ \$Revision: \s+ (\S+) }xms;
13
14 sub _definition {
15 my $themes = {
16 NYC => {
17 'HEADER_FONT_STYLE' => 'bf',
18 'HEADER_FONT_COLOR' => 'white',
19 'HEADER_BG_COLOR' => 'latextbl',
20 'DATA_BG_COLOR_ODD' => 'latextbl!25',
21 'DATA_BG_COLOR_EVEN' => 'latextbl!10',
22 'DEFINE_COLORS' => '\definecolor{latextbl}{RGB}{78,130,190}',
23 'HEADER_CENTERED' => 1,
24 'VERTICAL_RULES' => [ 1, 0, 0 ],
25 'HORIZONTAL_RULES' => [ 1, 1, 0 ],
26 'BOOKTABS' => 0,
27 'EXTRA_ROW_HEIGHT' => '1pt',
28 },
29 NYC2 => {
30 'HEADER_FONT_STYLE' => 'bf',
31 'HEADER_FONT_COLOR' => 'white',
32 'HEADER_BG_COLOR' => 'latextbl',
33 'DATA_BG_COLOR_ODD' => 'latextbl!25',
34 'DATA_BG_COLOR_EVEN' => 'latextbl!10',
35 'DEFINE_COLORS' => '\definecolor{latextbl}{RGB}{78,130,190}',
36 'HEADER_CENTERED' => 1,
37 'VERTICAL_RULES' => [ 1, 0, 0 ],
38 'HORIZONTAL_RULES' => [ 1, 0, 0 ],
39 'BOOKTABS' => 0,
40 'EXTRA_ROW_HEIGHT' => '1pt',
41 },
42 NYC3 => {
43 'HEADER_FONT_STYLE' => 'bf',
44 'HEADER_FONT_COLOR' => 'white',
45 'HEADER_BG_COLOR' => 'latextbl',
46 'DATA_BG_COLOR_ODD' => 'latextbl!25',
47 'DATA_BG_COLOR_EVEN' => 'latextbl!10',
48 'DEFINE_COLORS' => '\definecolor{latextbl}{RGB}{78,130,190}',
49 'HEADER_CENTERED' => 1,
50 'VERTICAL_RULES' => [ 1, 1, 1 ],
51 'HORIZONTAL_RULES' => [ 1, 2, 1 ],
52 'BOOKTABS' => 0,
53 'EXTRA_ROW_HEIGHT' => '1pt',
54 'RULES_COLOR_GLOBAL' =>
55 '\arrayrulecolor{white}\doublerulesepcolor{black}',
56 'RULES_WIDTH_GLOBAL' =>
57 '\setlength\arrayrulewidth{1pt}\setlength\doublerulesep{0pt}',
58 },
59 NYC4 => {
60 'HEADER_FONT_STYLE' => 'bf',
61 'HEADER_FONT_COLOR' => 'white',
62 'HEADER_BG_COLOR' => 'latextbl',
63 'DATA_BG_COLOR_ODD' => 'latextbl!25',
64 'DATA_BG_COLOR_EVEN' => 'latextbl!10',
65 'DEFINE_COLORS' => '\definecolor{latextbl}{RGB}{78,130,190}',
66 'HEADER_CENTERED' => 1,
67 'VERTICAL_RULES' => [ 0, 0, 0 ],
68 'HORIZONTAL_RULES' => [ 1, 1, 0 ],
69 'BOOKTABS' => 0,
70 'EXTRA_ROW_HEIGHT' => '1pt',
71 'RULES_COLOR_GLOBAL' =>
72 '\arrayrulecolor{black}\doublerulesepcolor{black}',
73 'RULES_WIDTH_GLOBAL' =>
74 '\setlength\arrayrulewidth{1pt}\setlength\doublerulesep{0pt}',
75 },
76 Redmond => {
77 'HEADER_FONT_STYLE' => 'bf',
78 'HEADER_FONT_COLOR' => 'white',
79 'HEADER_BG_COLOR' => 'black',
80 'DATA_BG_COLOR_ODD' => 'latextbl!25',
81 'DATA_BG_COLOR_EVEN' => 'latextbl!10',
82 'DEFINE_COLORS' => '\definecolor{latextbl}{RGB}{78,130,190}',
83 'STUB_ALIGN' => 'l',
84 'VERTICAL_RULES' => [ 0, 0, 0 ],
85 'HORIZONTAL_RULES' => [ 0, 2, 1 ],
86 'BOOKTABS' => 0,
87 'RULES_COLOR_GLOBAL' =>
88 '\arrayrulecolor{white}\doublerulesepcolor{black}',
89 'RULES_WIDTH_GLOBAL' =>
90 '\setlength\arrayrulewidth{1pt}\setlength\doublerulesep{0pt}',
91 'EXTRA_ROW_HEIGHT' => '1pt',
92 },
93 Redmond2 => {
94 'HEADER_FONT_STYLE' => 'bf',
95 'HEADER_FONT_COLOR' => 'white',
96 'HEADER_BG_COLOR' => 'black',
97 'DATA_BG_COLOR_ODD' => 'latextbl!25',
98 'DATA_BG_COLOR_EVEN' => 'latextbl!10',
99 'DEFINE_COLORS' => '\definecolor{latextbl}{RGB}{78,130,190}',
100 'STUB_ALIGN' => 'l',
101 'VERTICAL_RULES' => [ 0, 0, 0 ],
102 'HORIZONTAL_RULES' => [ 0, 2, 0 ],
103 'BOOKTABS' => 0,
104 'RULES_COLOR_GLOBAL' =>
105 '\arrayrulecolor{white}\doublerulesepcolor{black}',
106 'RULES_WIDTH_GLOBAL' =>
107 '\setlength\arrayrulewidth{1pt}\setlength\doublerulesep{0pt}',
108 'EXTRA_ROW_HEIGHT' => '1pt',
109 },
110 };
111 return $themes;
112 }
113
114 1;
115 __END__
116
117 =head1 NAME
118
119 LaTeX::Table::Themes::Beamer - Colorful LaTeX table themes optimized for presentations.
120
121 =head1 PROVIDES
122
123 This module provides following themes:
124
125 NYC
126 NYC2 # same, but without midline after header
127 NYC3 # with a white grid
128 NYC3 # with black horizontal lines
129 Redmond
130 Redmond2 # same, but without horizontal lines
131
132 =head1 REQUIRES
133
134 The themes defined in this module require following LaTeX packages:
135
136 \usepackage{array}
137 \usepackage{colortbl}
138 \usepackage{xcolor}
139
140 =head1 SEE ALSO
141
142 L<LaTeX::Table>, L<LaTeX::Table::Themes::ThemeI>
143
144 =head1 AUTHOR
145
146 Markus Riester C<< <mriester@gmx.de> >>
147
148 =head1 LICENSE AND COPYRIGHT
149
150 Copyright (c) 2006-2009, Markus Riester C<< <mriester@gmx.de> >>.
151
152 This module is free software; you can redistribute it and/or
153 modify it under the same terms as Perl itself. See L<perlartistic>.
154
155 =cut
156
157 # vim: ft=perl sw=4 ts=4 expandtab
0 #############################################################################
1 # $Author: markus $
2 # $Date: 2009-02-24 10:30:34 +0100 (Tue, 24 Feb 2009) $
3 # $Revision: 1326 $
4 #############################################################################
5
6 package LaTeX::Table::Themes::Booktabs;
7 use Moose;
8
9 with 'LaTeX::Table::Themes::ThemeI';
10
11 use version;
12 our ($VERSION) = '$Revision: 1326 $' =~ m{ \$Revision: \s+ (\S+) }xms;
13
14 sub _definition {
15 my $themes = {
16 'Zurich' => {
17 'HEADER_FONT_STYLE' => 'bf',
18 'HEADER_CENTERED' => 1,
19 'STUB_ALIGN' => 'l',
20 'VERTICAL_RULES' => [ 0, 0, 0 ],
21 'HORIZONTAL_RULES' => [ 1, 1, 0 ],
22 'BOOKTABS' => 1,
23 },
24 'Meyrin' => {
25 'STUB_ALIGN' => 'l',
26 'VERTICAL_RULES' => [ 0, 0, 0 ],
27 'HORIZONTAL_RULES' => [ 1, 1, 0 ],
28 'BOOKTABS' => 1,
29 },
30 };
31 return $themes;
32 }
33
34 1;
35 __END__
36
37 =head1 NAME
38
39 LaTeX::Table::Themes::Booktabs - Publication quality LaTeX table themes.
40
41 =head1 PROVIDES
42
43 This module provides following themes:
44
45 Meyrin # as described in the booktabs documentation
46 Zurich # header centered and in bold font
47
48 =head1 REQUIRES
49
50 The themes defined in this module require following LaTeX packages:
51
52 \usepackage{booktabs}
53
54 =head1 SEE ALSO
55
56 L<LaTeX::Table>, L<LaTeX::Table::Themes::ThemeI>
57
58 =head1 AUTHOR
59
60 Markus Riester C<< <mriester@gmx.de> >>
61
62 =head1 LICENSE AND COPYRIGHT
63
64 Copyright (c) 2006-2009, Markus Riester C<< <mriester@gmx.de> >>.
65
66 This module is free software; you can redistribute it and/or
67 modify it under the same terms as Perl itself. See L<perlartistic>.
68
69 =cut
70
71 # vim: ft=perl sw=4 ts=4 expandtab
0 #############################################################################
1 # $Author: markus $
2 # $Date: 2008-11-04 22:44:22 +0100 (Tue, 04 Nov 2008) $
3 # $Revision: 1151 $
4 #############################################################################
5
6 package LaTeX::Table::Themes::Classic;
7 use Moose;
8
9 with 'LaTeX::Table::Themes::ThemeI';
10
11 use version;
12 our ($VERSION) = '$Revision: 1151 $' =~ m{ \$Revision: \s+ (\S+) }xms;
13
14 sub _definition {
15 my $themes = {
16 'Dresden' => {
17 'HEADER_FONT_STYLE' => 'bf',
18 'HEADER_CENTERED' => 1,
19 'CAPTION_FONT_STYLE' => 'bf',
20 'VERTICAL_RULES' => [ 1, 2, 1 ],
21 'HORIZONTAL_RULES' => [ 1, 2, 0 ],
22 'BOOKTABS' => 0,
23 },
24 'Houston' => {
25 'HEADER_FONT_STYLE' => 'bf',
26 'HEADER_CENTERED' => 1,
27 'CAPTION_FONT_STYLE' => 'bf',
28 'VERTICAL_RULES' => [ 1, 2, 1 ],
29 'HORIZONTAL_RULES' => [ 1, 2, 1 ],
30 'EXTRA_ROW_HEIGHT' => '1pt',
31 'BOOKTABS' => 0,
32 },
33 'Berlin' => {
34 'HEADER_FONT_STYLE' => 'bf',
35 'HEADER_CENTERED' => 1,
36 'CAPTION_FONT_STYLE' => 'bf',
37 'VERTICAL_RULES' => [ 1, 1, 1 ],
38 'HORIZONTAL_RULES' => [ 1, 2, 0 ],
39 'BOOKTABS' => 0,
40 },
41 'Miami' => {
42 'HEADER_FONT_STYLE' => 'bf',
43 'HEADER_CENTERED' => 1,
44 'CAPTION_FONT_STYLE' => 'bf',
45 'STUB_ALIGN' => 'l',
46 'VERTICAL_RULES' => [ 0, 0, 0 ],
47 'HORIZONTAL_RULES' => [ 0, 1, 0 ],
48 'BOOKTABS' => 0,
49 },
50 'plain' => {
51 'STUB_ALIGN' => 'l',
52 'VERTICAL_RULES' => [ 0, 0, 0 ],
53 'HORIZONTAL_RULES' => [ 0, 0, 0 ],
54 'BOOKTABS' => 0,
55 },
56 };
57 return $themes;
58 }
59
60 1;
61 __END__
62
63 =head1 NAME
64
65 LaTeX::Table::Themes::Classic - Classic LaTeX table themes.
66
67 =head1 PROVIDES
68
69 This module provides following themes:
70
71 Berlin
72 Dresden
73 Houston
74 Miami
75 plain
76
77 =head1 REQUIRES
78
79 The themes defined in this module require no additional LaTeX packages.
80
81 =head1 SEE ALSO
82
83 L<LaTeX::Table>, L<LaTeX::Table::Themes::ThemeI>
84
85 =head1 AUTHOR
86
87 Markus Riester C<< <mriester@gmx.de> >>
88
89 =head1 LICENSE AND COPYRIGHT
90
91 Copyright (c) 2006-2009, Markus Riester C<< <mriester@gmx.de> >>.
92
93 This module is free software; you can redistribute it and/or
94 modify it under the same terms as Perl itself. See L<perlartistic>.
95
96 =cut
97
98 # vim: ft=perl sw=4 ts=4 expandtab
0 #############################################################################
1 # $Author: markus $
2 # $Date: 2009-02-03 17:09:45 +0100 (Tue, 03 Feb 2009) $
3 # $Revision: 1298 $
4 #############################################################################
5
6 package LaTeX::Table::Themes::Modern;
7 use Moose;
8
9 with 'LaTeX::Table::Themes::ThemeI';
10
11 use version;
12 our ($VERSION) = '$Revision: 1298 $' =~ m{ \$Revision: \s+ (\S+) }xms;
13
14 sub _definition {
15 my $themes = {
16 'Paris' => {
17 'HEADER_FONT_STYLE' => 'bf',
18 'HEADER_CENTERED' => 1,
19 'HEADER_BG_COLOR' => 'latextblgray',
20 'DEFINE_COLORS' =>
21 '\definecolor{latextblgray}{gray}{0.7}',
22 'CAPTION_FONT_STYLE' => 'bf',
23 'VERTICAL_RULES' => [ 1, 1, 1 ],
24 'HORIZONTAL_RULES' => [ 1, 1, 0 ],
25 'BOOKTABS' => 0,
26 },
27 'Muenchen' => {
28 'HEADER_FONT_STYLE' => 'bf',
29 'STUB_ALIGN' => 'l',
30 'DEFINE_COLORS' =>
31 '\definecolor{latexttbl}{RGB}{78,130,190}',
32 'CAPTION_FONT_STYLE' => 'bf',
33 'DATA_BG_COLOR_EVEN' => 'latextbl!20',
34 'VERTICAL_RULES' => [ 0, 0, 0 ],
35 'HORIZONTAL_RULES' => [ 0, 0, 0 ],
36 'BOOKTABS' => 1,
37 'EXTRA_ROW_HEIGHT' => '1pt',
38 },
39 };
40 return $themes;
41 }
42
43 1;
44 __END__
45
46 =head1 NAME
47
48 LaTeX::Table::Themes::Modern - Modern LaTeX table themes.
49
50 =head1 PROVIDES
51
52 This module provides following themes:
53
54 Paris
55 Muenchen
56
57 =head1 REQUIRES
58
59 The themes defined in this module requires following LaTeX packages:
60
61 \usepackage{xcolor}
62
63 =head1 NOTES
64
65 You probably want to use a Sans-serif font:
66
67 $tbl->set_fontfamily('sf');
68
69 =head1 SEE ALSO
70
71 L<LaTeX::Table>, L<LaTeX::Table::Themes::ThemeI>
72
73 =head1 AUTHOR
74
75 Markus Riester C<< <mriester@gmx.de> >>
76
77 =head1 LICENSE AND COPYRIGHT
78
79 Copyright (c) 2006-2009, Markus Riester C<< <mriester@gmx.de> >>.
80
81 This module is free software; you can redistribute it and/or
82 modify it under the same terms as Perl itself. See L<perlartistic>.
83
84 =cut
85
86 # vim: ft=perl sw=4 ts=4 expandtab
0 #############################################################################
1 # $Author: markus $
2 # $Date: 2009-02-04 16:33:40 +0100 (Wed, 04 Feb 2009) $
3 # $Revision: 1312 $
4 #############################################################################
5
6 package LaTeX::Table::Themes::ThemeI;
7
8 use strict;
9 use warnings;
10
11 use Moose::Role;
12
13 use version;
14 our ($VERSION) = '$Revision: 1312 $' =~ m{ \$Revision: \s+ (\S+) }xms;
15
16 requires '_definition';
17
18 around '_definition' => sub {
19 my $orig = shift;
20 my $self = shift;
21 my $ret = $orig->($self, @_);
22 for my $theme (keys %{$ret}) {
23 if (defined $ret->{$theme}->{BOOKTABS} && $ret->{$theme}->{BOOKTABS}) {
24 $ret->{$theme}->{RULES_CMD} =
25 [ '\toprule', '\midrule', '\midrule', '\bottomrule' ];
26 }
27 }
28 return $ret;
29 };
30
31 1;
32
33 __END__
34
35 =head1 NAME
36
37 LaTeX::Table::Themes::ThemeI - Interface for LaTeX table themes.
38
39 =head1 SYNOPSIS
40
41 package MyThemes::Custom;
42 use Moose;
43
44 with 'LaTeX::Table::Themes::ThemeI';
45
46 sub _definition {
47 return { CENTRALPARK =>
48 {
49 'HEADER_FONT_STYLE' => 'bf',
50 'HEADER_FONT_COLOR' => 'white',
51 'HEADER_BG_COLOR' => 'latextbl',
52 'DATA_BG_COLOR_ODD' => 'latextbl!25',
53 'DATA_BG_COLOR_EVEN' => 'latextbl!10',
54 'DEFINE_COLORS' => '\definecolor{latextbl}{RGB}{93,127,114}',
55 'HEADER_CENTERED' => 1,
56 'VERTICAL_RULES' => [ 1, 0, 0 ],
57 'HORIZONTAL_RULES' => [ 1, 1, 0 ],
58 'BOOKTABS' => 0,
59 'EXTRA_ROW_HEIGHT' => '1pt',
60 }};
61 }
62
63 1;
64
65 ..
66 $table->search_path( add => 'MyThemes');
67
68 =head1 DESCRIPTION
69
70 This is the theme interface (or L<Moose> role), that all theme objects must use.
71
72 =head1 CREATING THEMES
73
74 A theme is defined as an hash reference containing all options:
75
76 # a very ugly theme...
77 my $theme = {
78 'Duisburg' => {
79 'HEADER_FONT_STYLE' => 'sc',
80 'HEADER_FONT_COLOR' => 'white',
81 'HEADER_BG_COLOR' => 'blue',
82 'HEADER_CENTERED' => 1,
83 'DATA_BG_COLOR_ODD' => 'blue!30',
84 'DATA_BG_COLOR_EVEN' => 'blue!10',
85 'CAPTION_FONT_STYLE' => 'sc',
86 'VERTICAL_RULES' => [ 1, 2, 1 ],
87 'HORIZONTAL_RULES' => [ 1, 2, 0 ],
88 'EXTRA_ROW_HEIGHT' => '2pt',
89 'BOOKTABS' => 0,
90 },
91 };
92
93
94 =over
95
96 =item Fonts
97
98 C<HEADER_FONT_STYLE>, C<CAPTION_FONT_STYLE>. Valid values are I<bf> (bold),
99 I<it> (italics), I<sc> (caps) and I<tt> (typewriter). When this option is
100 undef, then header (or caption, respectively) is written in normal font.
101
102 =item Colors
103
104 C<HEADER_FONT_COLOR> can be used to specify a different font color for the
105 header. Requires the C<xcolor> LaTeX package.
106
107 Set C<HEADER_BG_COLOR> to use a background color in the header,
108 C<DATA_BG_COLOR_EVEN> and C<DATA_BG_COLOR_ODD> for even and odd data rows.
109 Requires the C<colortbl> and the C<xcolor> LaTeX package.
110
111 You can define colors with C<DEFINE_COLORS>, for example:
112
113 'DEFINE_COLORS' => '\definecolor{latextbl}{RGB}{78,130,190}',
114
115 =item Rules
116
117 =over
118
119 =item C<VERTICAL_RULES>, C<HORIZONTAL_RULES>
120
121 A reference to an array with three integers, e.g. C<[ 1, 2, 0 ]>. The first
122 integer defines the number of outer rules. The second the number of rules
123 after the header and after the first column. The third is the number of inner
124 rules. For example I<Dresden> is defined as:
125
126 'Dresden' => {
127 ...
128 'VERTICAL_RULES' => [ 1, 2, 1 ],
129 'HORIZONTAL_RULES' => [ 1, 2, 0 ],
130 }
131
132 The first integers define one outer rule - vertical and horizontal. So a box
133 is drawn around the table. The second integers define two rules between header
134 and table and two vertical rules between first and second column. And finally
135 the third integers define that columns are separated by a single vertical
136 rule whereas rows are not separated by horizontal lines.
137
138 =item C<RULES_COLOR_GLOBAL>
139
140 If your theme uses the C<colortbl> LaTeX package, this command should handle
141 the coloring of the rules. See the C<colortbl> documentation.
142
143 'RULES_COLOR_GLOBAL' =>
144 '\arrayrulecolor{white}\doublerulesepcolor{black}',
145
146 =item C<RULES_WIDTH_GLOBAL>
147
148 Code that controls the width of the rules. See for example the C<colortbl>
149 documentation.
150
151 'RULES_WIDTH_GLOBAL' =>
152 '\setlength\arrayrulewidth{1pt}\setlength\doublerulesep{0pt}',
153
154 =item C<RULES_CMD>
155
156 A reference to an array with four LaTeX commands for the top, mid (between header and
157 data), inner and bottom rules.
158
159 RULES_CMD => [ '\toprule', '\midrule', '\midrule', '\bottomrule' ];
160
161 =item C<BOOKTABS>
162
163 Use the C<booktabs> LaTeX package for "Publication quality tables". Instead of
164 C<\hline>, C<LaTeX::Table> then uses C<\toprule>, C<\midrule> and
165 C<\bottomrule>. 0 (don't use this package) or 1 (use it). A shortcut for
166
167 RULES_CMD => [ '\toprule', '\midrule', '\midrule', '\bottomrule' ];
168
169 =back
170
171 =item Misc
172
173 =over
174
175 =item C<EXTRA_ROW_HEIGHT>
176
177 Will set C<\extrarowheight> in the floating environment. Requires the C<array>
178 LaTeX package.
179
180 =item C<STUB_ALIGN>
181
182 Defines how the left-hand column, the stub, is aligned. Default is 'l' (left
183 aligned).
184
185 =item C<HEADER_CENTERED>
186
187 This controls the alignment of the header columns, excluding the stub when
188 C<STUB_ALIGN> is defined. Valid values are 0 (not centered) or 1 (centered).
189 Typically, it is recommended to center headers, but sometimes this does not
190 look right. In this case, (left) align the header manually.
191
192 =back
193
194 =back
195
196 You can either quickly add themes after initiation of an L<LaTeX::Table>:
197
198 $table->set_custom_themes($theme);
199
200 Or, you can build a L<"THEME MODULE"> and extend the list of predefined themes.
201
202 =head1 THEME MODULE
203
204 Now, to build a theme that you can easily load, take the L<"SYNOPSIS">
205 template, change it and then make it accessible in C<LaTeX::Table> by saving
206 it under the C<LaTeX::Table::Themes::*> namespace. Alternatively, you can use
207 the search_path() method to add custom paths. See L<"SYNOPSIS">. If your theme
208 looks nice, please contribute it.
209
210 =head1 SEE ALSO
211
212 L<LaTeX::Table>
213
214 =head1 AUTHOR
215
216 Markus Riester C<< <mriester@gmx.de> >>
217
218 =head1 LICENSE AND COPYRIGHT
219
220 Copyright (c) 2006-2009, Markus Riester C<< <mriester@gmx.de> >>.
221
222 This module is free software; you can redistribute it and/or
223 modify it under the same terms as Perl itself. See L<perlartistic>.
224
225 =cut
226
227 # vim: ft=perl sw=4 ts=4 expandtab
0 #############################################################################
1 # $Author: markus $
2 # $Date: 2009-02-04 12:25:08 +0100 (Wed, 04 Feb 2009) $
3 # $Revision: 1307 $
4 #############################################################################
5
6 package LaTeX::Table::Types::Ctable;
7 use Moose;
8
9 with 'LaTeX::Table::Types::TypeI';
10
11 use version;
12 our ($VERSION) = '$Revision: 1307 $' =~ m{ \$Revision: \s+ (\S+) }xms;
13
14 my $template =<<'EOT'
15 {[% DEFINE_COLORS_CODE %][% FONTSIZE_CODE %][% FONTFAMILY_CODE %][%
16 EXTRA_ROW_HEIGHT %][% RULES_WIDTH_GLOBAL %][% RESIZEBOX_BEGIN_CODE %]
17 \ctable[[% IF CAPTION %]caption = {[% CAPTION %]},
18 [% IF SHORTCAPTION %]cap = {[% SHORTCAPTION %]},
19 [% END %][% UNLESS CAPTION_TOP %]botcap,
20 [% END %][% END %][% IF POSITION %]pos = [% POSITION %],
21 [% END %][% IF LABEL %]label = {[% LABEL %]},
22 [% END %][% IF MAXWIDTH %]maxwidth = {[% MAXWIDTH %]},
23 [% END %][% IF WIDTH %]width = {[% WIDTH %]},
24 [% END %][% IF CENTER %]center,
25 [% END %][% IF LEFT %]left,
26 [% END %][% IF RIGHT %]right,
27 [% END %][% IF SIDEWAYS %]sideways,
28 [% END %][% IF STAR %]star,
29 [% END %][% IF CONTINUED %]continued = {[% CONTINUEDMSG %]},
30 [% END %]]{[% COLDEF %]}{[% FOOTTABLE %]}{
31 [% RULES_COLOR_GLOBAL %][% HEADER_CODE %][% DATA_CODE %]}
32 [% RESIZEBOX_END_CODE %]}
33 EOT
34 ;
35
36 has '+_tabular_environment' => (default => 'tabular');
37 has '+_template' => (default => $template);
38
39 1;
40
41 __END__
42
43 =head1 NAME
44
45 LaTeX::Table::Types::Ctable - Create LaTeX tables with the ctable package.
46
47 =head1 INTERFACE
48
49 =over
50
51 =item C<generate_latex_code>
52
53 =back
54
55 =head1 SEE ALSO
56
57 L<LaTeX::Table>, L<LaTeX::Table::Types::TypeI>
58
59 =head1 AUTHOR
60
61 Markus Riester C<< <mriester@gmx.de> >>
62
63 =head1 LICENSE AND COPYRIGHT
64
65 Copyright (c) 2006-2009, Markus Riester C<< <mriester@gmx.de> >>.
66
67 This module is free software; you can redistribute it and/or
68 modify it under the same terms as Perl itself. See L<perlartistic>.
69
70 =cut
71
72 # vim: ft=perl sw=4 ts=4 expandtab
0 #############################################################################
1 # $Author: markus $
2 # $Date: 2009-02-23 20:05:36 +0100 (Mon, 23 Feb 2009) $
3 # $Revision$
4 #############################################################################
5
6 package LaTeX::Table::Types::Longtable;
7 use Moose;
8
9 with 'LaTeX::Table::Types::TypeI';
10
11 use version;
12 our ($VERSION) = '$Revision: 1313 $' =~ m{ \$Revision: \s+ (\S+) }xms;
13
14 my $template =<<'EOT'
15 {
16 [% IF CONTINUED %]\addtocounter{table}{-1}[% END
17 %][% DEFINE_COLORS_CODE %][% EXTRA_ROW_HEIGHT %][% RULES_WIDTH_GLOBAL
18 %][% RULES_COLOR_GLOBAL %][% FONTSIZE_CODE %][% FONTFAMILY_CODE
19 %][%IF SIDEWAYS %]\begin{landscape}[% END
20 %][% IF CENTER %]\begin{center}
21 [% END %][% IF LEFT %]\begin{flushleft}
22 [% END %][% IF RIGHT %]\begin{flushright}
23 [% END %][% RESIZEBOX_BEGIN_CODE %]\begin{[% TABULAR_ENVIRONMENT %][% IF STAR %]*[% END %]}[% IF WIDTH %]{[%WIDTH %]}[% END %]{[% COLDEF %]}
24 [% IF CAPTION %][%IF CAPTION_TOP %]\caption[%IF SHORTCAPTION %][[%
25 SHORTCAPTION %]][% END %]{[% CAPTION %][% IF CONTINUED %] [% CONTINUEDMSG %][%
26 END %][% IF LABEL %]\label{[% LABEL %]}[% END %]}\\
27 [% END %][% END %][% HEADER_CODE %]\endfirsthead
28 [% IF CAPTION %][% IF CAPTION_TOP %][% IF TABLEHEADMSG %]\caption[]{[% TABLEHEADMSG %]}\\
29 [% END %][% END %][% END %]
30 [% HEADER_CODE %]\endhead
31 [% TABLETAIL %]\endfoot
32 [% TABLETAIL_LAST %]
33 [% IF CAPTION %][% UNLESS CAPTION_TOP %]\caption[%IF SHORTCAPTION %][[%
34 SHORTCAPTION %]][% END %]{[% CAPTION %][% IF CONTINUED %] [% CONTINUEDMSG %][%
35 END %][% IF LABEL %]\label{[% LABEL %]}[% END %]}\\
36 [% END %][% END %]\endlastfoot
37 [% DATA_CODE %]\end{[% TABULAR_ENVIRONMENT %][% IF STAR %]*[% END %]}
38 [% RESIZEBOX_END_CODE %][% IF CENTER %]\end{center}[% END %][% IF LEFT
39 %]\end{flushleft}[% END %][% IF RIGHT %]\end{flushright}[% END %][% IF
40 SIDEWAYS %]\end{landscape}[% END %]
41 }
42 EOT
43 ;
44
45 has '+_tabular_environment' => (default => 'longtable');
46 has '+_template' => (default => $template);
47
48 ###########################################################################
49 # Usage : $self->_get_tabletail_code(\@data, $final_tabletail);
50 # Purpose : generates the LaTeX code of the xtab tabletail
51 # Returns : LaTeX code
52 # Parameters : the data columns and a flag indicating whether it is the
53 # code for the final tail (1).
54
55 sub _get_tabletail_code {
56 my ( $self, $data, $final_tabletail ) = @_;
57
58 my $tbl = $self->_table_obj;
59 my $code;
60 my $hlines = $tbl->get_theme_settings->{'HORIZONTAL_RULES'};
61 my $vlines = $tbl->get_theme_settings->{'VERTICAL_RULES'};
62 my $linecode1 = $self->_get_hline_code($self->_RULE_MID_ID);
63 my $linecode2 = $self->_get_hline_code($self->_RULE_BOTTOM_ID);
64
65 # if custom table tail is defined, then return it
66 if ( $tbl->get_tabletail ) {
67 $code = $tbl->get_tabletail;
68 }
69 elsif ( !$final_tabletail ) {
70 my @cols = $tbl->_get_data_summary();
71 my $nu_cols = scalar @cols;
72
73 my $v0 = q{|} x $vlines->[0];
74 $code = "$linecode1\\multicolumn{$nu_cols}{${v0}r$v0}{{"
75 . $tbl->get_tabletailmsg
76 . "}} \\\\\n";
77 }
78 if ($final_tabletail) {
79 return q{};
80 }
81 return "$code$linecode2";
82 }
83
84
85 1;
86 __END__
87
88 =head1 NAME
89
90 LaTeX::Table::Types::Longtable - Create multi-page LaTeX tables with the longtable package.
91
92 =head1 INTERFACE
93
94 =over
95
96 =item C<generate_latex_code>
97
98 =back
99
100 =head1 SEE ALSO
101
102 L<LaTeX::Table>, L<LaTeX::Table::Types::TypeI>
103
104 =head1 AUTHOR
105
106 Markus Riester C<< <mriester@gmx.de> >>
107
108 =head1 LICENSE AND COPYRIGHT
109
110 Copyright (c) 2006-2009, Markus Riester C<< <mriester@gmx.de> >>.
111
112 This module is free software; you can redistribute it and/or
113 modify it under the same terms as Perl itself. See L<perlartistic>.
114
115 =cut
116
117 # vim: ft=perl sw=4 ts=4 expandtab
0 #############################################################################
1 # $Author: markus $
2 # $Date: 2009-02-04 12:25:08 +0100 (Wed, 04 Feb 2009) $
3 # $Revision: 1307 $
4 #############################################################################
5
6 package LaTeX::Table::Types::Std;
7 use Moose;
8
9 with 'LaTeX::Table::Types::TypeI';
10
11 use version;
12 our ($VERSION) = '$Revision: 1307 $' =~ m{ \$Revision: \s+ (\S+) }xms;
13
14 my $template =<<'EOT'
15 [%IF CONTINUED %]\addtocounter{table}{-1}[% END %][% DEFINE_COLORS_CODE %][% IF ENVIRONMENT %]\begin{[% IF SIDEWAYS %]sidewaystable[% ELSE %][% ENVIRONMENT %][% END %][% IF STAR %]*[% END %]}[% IF POSITION %][[% POSITION %]][% END %]
16 [% FONTSIZE_CODE %][% FONTFAMILY_CODE %][% RULES_WIDTH_GLOBAL %][% IF CENTER %]\centering
17 [% END %][% IF LEFT %]\raggedright
18 [% END %][% IF RIGHT %]\raggedleft
19 [% END %][% IF CAPTION_TOP %][% IF CAPTION %]\[% CAPTION_CMD %][% IF SHORTCAPTION %][[% SHORTCAPTION %]][% END %]{[% CAPTION %][% IF CONTINUED %] [% CONTINUEDMSG %][% END %]}
20 [% END %][% END %][% END %][% EXTRA_ROW_HEIGHT %][% RESIZEBOX_BEGIN_CODE %]\begin{[% TABULAR_ENVIRONMENT %]}[% IF WIDTH %]{[% WIDTH %]}[% END %]{[% COLDEF %]}
21 [% RULES_COLOR_GLOBAL %][% HEADER_CODE %][% DATA_CODE %]\end{[%
22 TABULAR_ENVIRONMENT %]}[% RESIZEBOX_END_CODE %][% IF ENVIRONMENT %][% UNLESS CAPTION_TOP %][% IF CAPTION %]
23 \[% CAPTION_CMD %][% IF SHORTCAPTION %][[% SHORTCAPTION %]][% END %]{[% CAPTION %][% IF CONTINUED %] [% CONTINUEDMSG %][% END %]}[% END %][% END %][%IF LABEL %]
24 \label{[% LABEL %]}[% END %]
25 \end{[% IF SIDEWAYS %]sidewaystable[% ELSE %][% ENVIRONMENT %][% END %][% IF STAR %]*[% END %]}[% END %]
26 EOT
27 ;
28
29 has '+_tabular_environment' => (default => 'tabular');
30 has '+_template' => (default => $template);
31
32 1;
33
34 __END__
35
36 =head1 NAME
37
38 LaTeX::Table::Types::Std - Create standard LaTeX tables.
39
40 =head1 INTERFACE
41
42 =over
43
44 =item C<generate_latex_code>
45
46 =back
47
48 =head1 SEE ALSO
49
50 L<LaTeX::Table>, L<LaTeX::Table::Types::TypeI>
51
52 =head1 AUTHOR
53
54 Markus Riester C<< <mriester@gmx.de> >>
55
56 =head1 LICENSE AND COPYRIGHT
57
58 Copyright (c) 2006-2009, Markus Riester C<< <mriester@gmx.de> >>.
59
60 This module is free software; you can redistribute it and/or
61 modify it under the same terms as Perl itself. See L<perlartistic>.
62
63 =cut
64
65 # vim: ft=perl sw=4 ts=4 expandtab
0 #############################################################################
1 # $Author: markus $
2 # $Date: 2009-05-28 18:46:45 +0200 (Thu, 28 May 2009) $
3 # $Revision: 1612 $
4 #############################################################################
5
6 package LaTeX::Table::Types::TypeI;
7
8 use strict;
9 use warnings;
10
11 use Moose::Role;
12 use Template;
13
14 use version;
15 our ($VERSION) = '$Revision: 1612 $' =~ m{ \$Revision: \s+ (\S+) }xms;
16
17 use Scalar::Util qw(reftype);
18
19 use Carp;
20
21 has '_table_obj' => ( is => 'rw', isa => 'LaTeX::Table', required => 1 );
22 has '_tabular_environment' => ( is => 'ro', required => 1 );
23 has '_template' => ( is => 'ro', required => 1 );
24
25 has '_RULE_TOP_ID' => ( is => 'ro', default => 0 );
26 has '_RULE_MID_ID' => ( is => 'ro', default => 1 );
27 has '_RULE_INNER_ID' => ( is => 'ro', default => 2 );
28 ## no critic (ValuesAndExpressions::ProhibitMagicNumbers)
29 has '_RULE_BOTTOM_ID' => ( is => 'ro', default => 3 );
30 ## use critic
31
32 1;
33
34 ###########################################################################
35 # Usage : $self->_header(\@header,\@data);
36 # Purpose : create the LaTeX header
37 # Returns : LaTeX code
38 # Parameters : header and data columns
39 # Throws :
40 # Comments : n/a
41 # See also : _footer
42
43 sub generate_latex_code {
44 my ( $self, $header, $data ) = @_;
45
46 my $tbl = $self->_table_obj;
47
48 # if specified, use coldef, otherwise guess a good definition
49 my $table_def;
50 if ( $tbl->get_coldef ) {
51 $table_def = $tbl->get_coldef;
52 }
53 else {
54 $table_def = $tbl->_get_coldef_code($data);
55 }
56
57 my $center = $tbl->get_center;
58
59 if ( $tbl->get__default_align ) {
60 $center = 1;
61 }
62 my $header_code = $self->_get_header_columns_code($header);
63
64 my $template_vars = {
65 'CENTER' => $center,
66 'LEFT' => $tbl->get_left(),
67 'RIGHT' => $tbl->get_right(),
68 'ENVIRONMENT' => $tbl->get_environment,
69 'FONTFAMILY' => $tbl->get_fontfamily(),
70 'FONTFAMILY_CODE' => $self->_get_fontfamily_code(),
71 'FONTSIZE' => $tbl->get_fontsize(),
72 'FONTSIZE_CODE' => $self->_get_fontsize_code(),
73 'FOOTTABLE' => $tbl->get_foottable(),
74 'POSITION' => $tbl->get_position(),
75 'CAPTION_TOP' => $tbl->get_caption_top(),
76 'CAPTION' => $self->_get_caption(),
77 'CAPTION_CMD' => $self->_get_caption_command(),
78 'CONTINUED' => $tbl->get_continued(),
79 'CONTINUEDMSG' => $tbl->get_continuedmsg(),
80 'SHORTCAPTION' => $self->_get_shortcaption(),
81 'SIDEWAYS' => $tbl->get_sideways(),
82 'STAR' => $tbl->get_star(),
83 'EXTRA_ROW_HEIGHT' => $self->_get_extra_row_height_code(),
84 'RULES_COLOR_GLOBAL' => $self->_get_rules_color_global_code(),
85 'RULES_WIDTH_GLOBAL' => $self->_get_rules_width_global_code(),
86 'RESIZEBOX_BEGIN_CODE' => $self->_get_begin_resizebox_code(),
87 'RESIZEBOX_END_CODE' => $self->_get_end_resizebox_code(),
88 'WIDTH' => $tbl->get_width(),
89 'MAXWIDTH' => $tbl->get_maxwidth(),
90 'COLDEF' => $table_def,
91 'LABEL' => $tbl->get_label(),
92 'HEADER_CODE' => $header_code,
93 'TABLEHEADMSG' => $tbl->get_tableheadmsg(),
94 'TABLEHEAD' => $self->_get_tablehead_code( $header_code ),
95 'TABLETAIL' => $self->_get_tabletail_code( $data, 0 ),
96 'TABLETAIL_LAST' => $self->_get_tabletail_code( $data, 1 ),
97 'XENTRYSTRETCH_CODE' => $self->_get_xentrystretch_code(),
98 'DATA_CODE' => $self->_get_data_code(),
99 'TABULAR_ENVIRONMENT' => $self->_get_tabular_environment(),
100 'DEFINE_COLORS_CODE' => $self->_get_colordef_code,
101 };
102
103 my $template_obj = Template->new();
104 my $template = $self->_template;
105
106 if ($tbl->get_custom_template) {
107 $template = $tbl->get_custom_template;
108 }
109
110 my $template_output;
111
112 $template_obj->process( \$template, $template_vars, \$template_output )
113 or croak $template_obj->error();
114 return $template_output;
115 }
116
117 sub _get_data_code {
118 my ($self) = @_;
119 my $code = q{};
120 my $tbl = $self->_table_obj;
121
122 my $theme = $tbl->get_theme_settings;
123 my $i = 0;
124 my $row_id = 0;
125
126 # check the data and apply callback function
127 my @data = $tbl->_examine_data;
128 my @code;
129 ROW:
130 for my $row (@data) {
131 $i++;
132
133 # empty rows produce a horizontal line
134 if ( !@{$row} ) {
135 push @code, $self->_get_hline_code( $self->_RULE_INNER_ID, 1);
136 next ROW;
137 }
138 else {
139
140 # single column rows that start with a backslash are just
141 # printed out
142 if ( $tbl->_row_is_latex_command($row) ) {
143 push @code, $row->[0] . "\n";
144 next ROW;
145 }
146
147 $row_id++;
148
149 # now print the row LaTeX code
150 my $bgcolor = $theme->{'DATA_BG_COLOR_EVEN'};
151 if ( ( $row_id % 2 ) == 1 ) {
152 $bgcolor = $theme->{'DATA_BG_COLOR_ODD'};
153 }
154 push @code, $tbl->_get_row_array( $row, $bgcolor, 0 );
155
156 # do we have to draw a horizontal line?
157 if ( $i == scalar @data ) {
158 push @code, $self->_get_hline_code( $self->_RULE_BOTTOM_ID );
159 }
160 else {
161 push @code, $self->_get_hline_code( $self->_RULE_INNER_ID );
162 }
163 }
164 }
165
166 return $self->_align_code(\@code);
167 }
168
169 sub _align_code {
170 my ( $self, $code_ref ) = @_;
171 my %max;
172 for my $row (@{$code_ref}) {
173 next if (!defined reftype $row);
174 for my $i ( 0 .. scalar( @{$row} ) - 1 ) {
175 $row->[$i] =~ s{^\s+|\s+$}{}gxms;
176 my $l = length $row->[$i];
177 if (!defined $max{$i} || $max{$i} < $l) {
178 $max{$i} = $l;
179 }
180 }
181 }
182
183 my $code = q{};
184 ROW:
185 for my $row (@{$code_ref}) {
186 if (!defined reftype $row) {
187 $code .= $row;
188 next ROW;
189 }
190 for my $i ( 0 .. scalar( @{$row} ) - 1 ) {
191 $row->[$i] = sprintf '%-*s', $max{$i}, $row->[$i];
192 }
193 $code .= join( ' & ', @{$row} ) . " \\\\\n";
194 }
195 return $code;
196 }
197
198 sub _get_caption_command {
199 my ($self) = @_;
200 my $tbl = $self->_table_obj;
201 my $c_caption = 'caption';
202 if ( $tbl->get_caption_top ) {
203 $c_caption = $tbl->get_caption_top;
204 $c_caption =~ s{ \A \\ }{}xms;
205 if ( $c_caption eq '1' ) {
206 $c_caption = 'caption';
207 }
208 }
209 return $c_caption;
210 }
211
212 sub _get_colordef_code {
213 my ($self) = @_;
214 my $tbl = $self->_table_obj;
215 my $colordef = q{};
216 if ( defined $tbl->get_theme_settings->{DEFINE_COLORS} ) {
217 $colordef = $tbl->get_theme_settings->{DEFINE_COLORS} . "\n";
218 }
219 return $colordef;
220 }
221
222 sub _get_begin_resizebox_code {
223 my ($self) = @_;
224 if ( $self->_table_obj->get_resizebox ) {
225 my $rb_width = $self->_table_obj->get_resizebox->[0];
226 my $rb_height = q{!};
227 if ( defined $self->_table_obj->get_resizebox->[1] ) {
228 $rb_height = $self->_table_obj->get_resizebox->[1];
229 }
230 return "\\resizebox{$rb_width}{$rb_height}{\n";
231 }
232 return q{};
233 }
234
235 sub _get_end_resizebox_code {
236 my ($self) = @_;
237 my $end_resizebox = q{};
238 if ( $self->_table_obj->get_resizebox ) {
239 $end_resizebox = "}\n";
240 }
241 return $end_resizebox;
242 }
243
244 ###########################################################################
245 # Usage : $self->_get_caption_code($header);
246 # Purpose : generates the LaTeX code of the caption
247 # Returns : LaTeX code
248 # Parameters : called from _header?
249 # Comments : header specifies whether this function has been called in
250 # the header or footer. ignored for xtab, because there it
251 # is always placed on top
252
253 sub _get_caption {
254 my ( $self, $header ) = @_;
255 my $caption = q{};
256 my $s_caption = q{};
257 my $tbl = $self->_table_obj;
258
259 if ( !$tbl->get_caption) {
260 if (!$tbl->get_maincaption) {
261 return 0;
262 }
263 }
264 else {
265 $caption = $tbl->get_caption;
266 }
267
268 my $theme = $tbl->get_theme_settings;
269
270 my $tmp = q{};
271 if ( $tbl->get_maincaption ) {
272 $tmp = $tbl->get_maincaption . '. ';
273 if ( defined $theme->{CAPTION_FONT_STYLE} ) {
274 $tmp = $tbl->_add_font_family( $tmp,
275 $theme->{CAPTION_FONT_STYLE} );
276 }
277 }
278
279 return $tmp . $caption;
280 }
281
282 sub _get_shortcaption {
283 my ($self) = @_;
284 my $tbl = $self->_table_obj;
285 if ( $tbl->get_maincaption ) {
286 return $tbl->get_maincaption;
287 }
288 if ( $tbl->get_shortcaption ) {
289 return $tbl->get_shortcaption;
290 }
291 return 0;
292 }
293
294 sub _get_extra_row_height_code {
295 my ($self) = @_;
296 if ( defined $self->_table_obj->get_theme_settings->{EXTRA_ROW_HEIGHT} ) {
297 return '\setlength{\extrarowheight}{'
298 . $self->_table_obj->get_theme_settings->{EXTRA_ROW_HEIGHT}
299 . "}\n";
300 }
301 return q{};
302 }
303
304 sub _get_rules_color_global_code {
305 my ($self) = @_;
306 if ( defined $self->_table_obj->get_theme_settings->{RULES_COLOR_GLOBAL} ) {
307 return $self->_table_obj->get_theme_settings->{RULES_COLOR_GLOBAL}
308 . "\n";
309 }
310 return q{};
311 }
312
313 sub _get_rules_width_global_code {
314 my ($self) = @_;
315 if ( defined $self->_table_obj->get_theme_settings->{RULES_WIDTH_GLOBAL} ) {
316 return $self->_table_obj->get_theme_settings->{RULES_WIDTH_GLOBAL}
317 . "\n";
318 }
319 return q{};
320 }
321
322 sub _get_hline_code {
323 my ( $self, $id, $single ) = @_;
324 my $tbl = $self->_table_obj;
325 my $theme = $tbl->get_theme_settings;
326 my $hlines = $theme->{'HORIZONTAL_RULES'};
327 my $line = '\hline';
328 if ( defined $theme->{RULES_CMD} && reftype $theme->{RULES_CMD} eq 'ARRAY') {
329 $line = $theme->{RULES_CMD}->[$id];
330 }
331 if ( $id == $self->_RULE_BOTTOM_ID ) {
332 $id = 0;
333 }
334 # just one line?
335 if (defined $single && $single) {
336 return "$line\n";
337 }
338 return "$line\n" x $hlines->[$id];
339 }
340
341 ###########################################################################
342 # Usage : $self->_get_fontsize_code();
343 # Purpose : generates the LaTeX code of the fontsize (e.g. \small, \large)
344 # Returns : LaTeX code
345 # Parameters : none
346 # Throws : exception if fontsize is not valid
347
348 sub _get_fontsize_code {
349 my ($self) = @_;
350 my %valid = (
351 'tiny' => 1,
352 'scriptsize' => 1,
353 'footnotesize' => 1,
354 'small' => 1,
355 'normal' => 1,
356 'large' => 1,
357 'Large' => 1,
358 'LARGE' => 1,
359 'huge' => 1,
360 'Huge' => 1,
361 );
362 my $size = $self->_table_obj->get_fontsize;
363 return q{} if !$size;
364
365 if ( !defined $valid{$size} ) {
366 $self->_table_obj->invalid_option_usage(
367 'custom_themes',
368 "Size not known: $size. Valid sizes are: " . join ', ',
369 sort keys %valid
370 );
371 }
372 return "\\$size\n";
373 }
374
375
376 sub _get_fontfamily_code {
377 my ($self) = @_;
378 my %valid = (
379 'rm' => 1,
380 'sf' => 1,
381 'tt' => 1,
382 );
383 my $family = $self->_table_obj->get_fontfamily;
384 return q{} if !$family;
385
386 if ( !defined $valid{$family} ) {
387 $self->_table_obj->invalid_option_usage(
388 'fontfamily',
389 "Family not known: $family. Valid families are: " . join ', ',
390 sort keys %valid
391 );
392 }
393 return "\\${family}family\n";
394 }
395
396 sub _get_tabular_environment {
397 my ($self) = @_;
398 my $res;
399 my $tbl = $self->_table_obj;
400
401 if ( $tbl->get_custom_tabular_environment ) {
402 $res = $tbl->get_custom_tabular_environment;
403 }
404 else {
405 $res = $self->_tabular_environment;
406 }
407 if ( $tbl->get_width ) {
408 if ( !$tbl->get_width_environment ) {
409 $res .= q{*};
410 }
411 elsif ( $tbl->get_type ne 'longtable') { #want the ltxtable package?
412 $res = $tbl->get_width_environment;
413 }
414 }
415 return $res;
416 }
417
418 ###########################################################################
419 # Usage : $self->_get_header_columns_code(\@header);
420 # Purpose : generate the header LaTeX code
421 # Returns : LaTeX code
422 # Parameters : header columns
423 # Throws :
424 # Comments : n/a
425 # See also : _get_row_code
426
427 sub _get_header_columns_code {
428 my ( $self, $header ) = @_;
429 my $tbl = $self->_table_obj;
430 my $code = q{};
431 my $theme = $tbl->get_theme_settings;
432
433 my $i = 0;
434
435 my @code = ( $self->_get_hline_code( $self->_RULE_TOP_ID ) );
436
437 CENTER_ROW:
438 for my $row ( @{$header} ) {
439 my @cols = @{$row};
440 if ( scalar @cols == 0 ) {
441 push @code, $self->_get_hline_code( $self->_RULE_INNER_ID, 1);
442 next CENTER_ROW;
443 }
444 if ( $tbl->_row_is_latex_command($row) ) {
445 push @code, $cols[0] . "\n";
446 next CENTER_ROW;
447 }
448
449 my $j = 0;
450
451 for my $col (@cols) {
452 if ( $tbl->get_header_sideways() ) {
453 my $col_def = $tbl->_get_mc_def($col);
454 $col_def->{value}
455 = '\begin{sideways}' . $col_def->{value} . '\end{sideways}';
456 $col = $tbl->_get_mc_value($col_def);
457 }
458 #next if $col =~ m{\A \\ }xms;
459 if ( $tbl->get_callback ) {
460 $col = $tbl->_apply_callback( $i, $j, $col, 1 );
461 }
462 $col = $tbl->_apply_header_formatting( $col, (!defined
463 $theme->{STUB_ALIGN} || $j > 0) );
464 $j += $tbl->_extract_number_columns($col);
465 }
466
467 push @code, $tbl->_get_row_array( \@cols, $theme->{'HEADER_BG_COLOR'}, 1 );
468 $i++;
469 }
470
471 # without header, just draw the topline, not this midline
472 if ($i) {
473 push @code, $self->_get_hline_code( $self->_RULE_MID_ID );
474 }
475 return $self->_align_code(\@code);
476 }
477
478 sub _get_tabletail_code { return q{}; }
479 sub _get_xentrystretch_code { return q{}; }
480 sub _get_tablehead_code { return q{}; }
481
482 1;
483 __END__
484
485 =head1 NAME
486
487 LaTeX::Table::Types::TypeI - Interface for LaTeX table types.
488
489 =head1 SYNOPSIS
490
491 =head1 DESCRIPTION
492
493 This is the type interface (or L<Moose> role), that all type objects must use.
494 L<LaTeX::Table> delegates the boring work of building the LaTeX code to type
495 objects. It stores all information we have in easy to use L<"TEMPLATE
496 VARIABLES">. L<LaTeX::Table> ships with very flexible templates, but you can
497 also use the template variables defined here to build custom templates.
498
499 =head1 INTERFACE
500
501 =over
502
503 =item C<generate_latex_code>
504
505 =back
506
507 =head1 TEMPLATE VARIABLES
508
509 CAUTION: This API is not stable. If you build custom templates, they might not
510 work in future versions!
511
512 Most options are accessable here:
513
514 =over
515
516 =item C<CENTER, LEFT, RIGHT>
517
518 Example:
519
520 [% IF CENTER %]\centering
521 [% END %]
522
523 =item C<ENVIRONMENT, STAR, POSITION, SIDEWAYS>
524
525 These options for floating environments are typically used like:
526
527 [% IF ENVIRONMENT %]\begin{[% ENVIRONMENT %][% IF STAR %]*[% END %]}[% IF POSITION %][[% POSITION %]][% END %]
528 ...
529 [% END %]
530 # the tabular environment here
531 ...
532 [% IF ENVIRONMENT %] ...
533 \end{[% ENVIRONMENT %][% IF STAR %]*[% END %]}[% END %]
534
535 =item C<CAPTION_TOP, CAPTION_CMD, SHORTCAPTION, CAPTION, CONTINUED, CONTINUEDMSG>
536
537 The variables to build the caption command. Note that there is NO template for
538 the C<maincaption> option. C<CAPTION> already includes this maincaption if
539 specified.
540
541 =item C<LABEL>
542
543 The label:
544
545 [% IF LABEL %]\label{[% LABEL %]}[% END %]
546
547 =item C<TABULAR_ENVIRONMENT, WIDTH, COLDEF>
548
549 These three options define the tabular environment:
550
551 \begin{[% TABULAR_ENVIRONMENT %]}[% IF WIDTH %]{[% WIDTH %]}[% END %]{[% COLDEF %]}
552
553 =back
554
555 In addition, some variables already contain formatted LaTeX code:
556
557 =over
558
559 =item C<HEADER_CODE>
560
561 The formatted header:
562
563 \toprule
564 \multicolumn{2}{c}{Item} & \\
565 \cmidrule(r){1-2}
566 Animal & Description & Price \\
567 \midrule
568
569 =item C<DATA_CODE>
570
571 The formatted data:
572
573 Gnat & per gram & 13.65 \\
574 & each & 0.01 \\
575 Gnu & stuffed & 92.59 \\
576 Emu & stuffed & 33.33 \\
577 Armadillo & frozen & 8.99 \\
578 \bottomrule
579
580 =item C<FONTFAMILY_CODE, FONTSIZE_CODE>
581
582 =item C<RESIZEBOX_BEGIN_CODE, RESIZEBOX_END_CODE>
583
584 Everything between these two template variables is resized according the
585 C<resizebox> option.
586
587 =back
588
589 =head1 SEE ALSO
590
591 L<LaTeX::Table>
592
593 The predefined templates: L<LaTeX::Table::Types::Std>,
594 L<LaTeX::Table::Types::Ctable>, L<LaTeX::Table::Types::Xtab>
595
596 =head1 AUTHOR
597
598 Markus Riester C<< <mriester@gmx.de> >>
599
600 =head1 LICENSE AND COPYRIGHT
601
602 Copyright (c) 2006-2009, Markus Riester C<< <mriester@gmx.de> >>.
603
604 This module is free software; you can redistribute it and/or
605 modify it under the same terms as Perl itself. See L<perlartistic>.
606
607 =cut
608
609 # vim: ft=perl sw=4 ts=4 expandtab
0 #############################################################################
1 # $Author: markus $
2 # $Date: 2009-05-20 21:07:28 +0200 (Wed, 20 May 2009) $
3 # $Revision: 1564 $
4 #############################################################################
5
6 package LaTeX::Table::Types::Xtab;
7 use Moose;
8
9 with 'LaTeX::Table::Types::TypeI';
10
11 use version;
12 our ($VERSION) = '$Revision: 1564 $' =~ m{ \$Revision: \s+ (\S+) }xms;
13
14 my $template =<<'EOT'
15 {
16 [%IF CONTINUED %]\addtocounter{table}{-1}[% END %][% DEFINE_COLORS_CODE %][%
17 EXTRA_ROW_HEIGHT %][% RULES_WIDTH_GLOBAL %][% RULES_COLOR_GLOBAL %][%
18 FONTSIZE_CODE %][% FONTFAMILY_CODE %][%IF SIDEWAYS %]\begin{landscape}[% END %][% IF CAPTION %][%IF CAPTION_TOP
19 %]\topcaption[% ELSE %]\bottomcaption[% END %][%IF SHORTCAPTION %][[% SHORTCAPTION %]][% END %]{[% CAPTION %][% IF CONTINUED %] [% CONTINUEDMSG %][% END %]}
20 [% END %][% XENTRYSTRETCH %][% IF LABEL %]\label{[% LABEL %]}
21 [% END %]
22 [% TABLEHEAD %]
23 [% TABLETAIL %]
24 [% TABLETAIL_LAST %]
25 [% IF CENTER %]\begin{center}
26 [% END %][% IF LEFT %]\begin{flushleft}
27 [% END %][% IF RIGHT %]\begin{flushright}
28 [% END %][% RESIZEBOX_BEGIN_CODE %]\begin{[% TABULAR_ENVIRONMENT %][% IF STAR %]*[% END %]}[% IF WIDTH %]{[%WIDTH %]}[% END %]{[% COLDEF %]}
29 [% DATA_CODE %]\end{[% TABULAR_ENVIRONMENT %][% IF STAR %]*[% END %]}
30 [% RESIZEBOX_END_CODE %][% IF CENTER %]\end{center}[% END %][% IF LEFT
31 %]\end{flushleft}[% END %][% IF RIGHT %]\end{flushright}[% END %][% IF
32 SIDEWAYS %]\end{landscape}[% END %]
33 }
34 EOT
35 ;
36
37 has '+_tabular_environment' => (default => 'xtabular');
38 has '+_template' => (default => $template);
39
40 sub _get_tablehead_code {
41 my ($self, $code) =@_;
42 my $tbl = $self->_table_obj;
43
44 my $tablehead = q{};
45 my @summary = $tbl->_get_data_summary();
46
47 if ( $tbl->get_caption_top && $tbl->get_tableheadmsg ) {
48 my $continued_caption = '\\multicolumn{'
49 . scalar(@summary)
50 . '}{c}{{ \normalsize \tablename\ \thetable: '
51 . $tbl->get_tableheadmsg
52 . "}}\\\\[\\abovecaptionskip]\n";
53 $tablehead
54 = "\\tablefirsthead{$code}\n\\tablehead{$continued_caption$code}\n";
55
56 # $tablehead = "\\tablehead{$code}";
57 }
58 else {
59 $tablehead = "\\tablehead{$code}";
60 }
61 return $tablehead;
62 }
63
64 ###########################################################################
65 # Usage : $self->_get_tabletail_code(\@data, $final_tabletail);
66 # Purpose : generates the LaTeX code of the xtab tabletail
67 # Returns : LaTeX code
68 # Parameters : the data columns and a flag indicating whether it is the
69 # code for the final tail (1).
70
71 sub _get_tabletail_code {
72 my ( $self, $data, $final_tabletail ) = @_;
73
74 my $tbl = $self->_table_obj;
75 my $code;
76 my $hlines = $tbl->get_theme_settings->{'HORIZONTAL_RULES'};
77 my $vlines = $tbl->get_theme_settings->{'VERTICAL_RULES'};
78 my $linecode1 = $self->_get_hline_code($self->_RULE_MID_ID);
79 my $linecode2 = $self->_get_hline_code($self->_RULE_BOTTOM_ID);
80
81 # if custom table tail is defined, then return it
82 if ( $tbl->get_tabletail ) {
83 $code = $tbl->get_tabletail;
84 }
85 elsif ( !$final_tabletail ) {
86 my @cols = $tbl->_get_data_summary();
87 my $nu_cols = scalar @cols;
88
89 my $v0 = q{|} x $vlines->[0];
90 $code = "$linecode1\\multicolumn{$nu_cols}{${v0}r$v0}{{"
91 . $tbl->get_tabletailmsg
92 . "}} \\\\\n";
93 }
94 if ($final_tabletail) {
95 return '\tablelasttail{}';
96 }
97 return "\\tabletail{$code$linecode2}";
98 }
99
100 sub _get_xentrystretch_code {
101 my ($self) = @_;
102 my $tbl = $self->_table_obj;
103 if ( $tbl->get_xentrystretch ) {
104 my $xs = $tbl->get_xentrystretch();
105 if ( $xs !~ /\A-?(?:\d+(?:\.\d*)?|\.\d+)\z/xms ) {
106 $tbl->invalid_option_usage( 'xentrystretch',
107 'Not a number: ' . $tbl->get_xentrystretch );
108 }
109 return "\\xentrystretch{$xs}\n";
110 }
111 return q{};
112 }
113
114
115 1;
116 __END__
117
118 =head1 NAME
119
120 LaTeX::Table::Types::Xtab - Create multi-page LaTeX tables with the xtabular package.
121
122 =head1 INTERFACE
123
124 =over
125
126 =item C<generate_latex_code>
127
128 =back
129
130 =head1 SEE ALSO
131
132 L<LaTeX::Table>, L<LaTeX::Table::Types::TypeI>
133
134 =head1 AUTHOR
135
136 Markus Riester C<< <mriester@gmx.de> >>
137
138 =head1 LICENSE AND COPYRIGHT
139
140 Copyright (c) 2006-2009, Markus Riester C<< <mriester@gmx.de> >>.
141
142 This module is free software; you can redistribute it and/or
143 modify it under the same terms as Perl itself. See L<perlartistic>.
144
145 =cut
146
147 # vim: ft=perl sw=4 ts=4 expandtab
0 #############################################################################
1 # $Author: markus $
2 # $Date: 2009-05-29 10:13:11 +0200 (Fri, 29 May 2009) $
3 # $Revision: 1615 $
4 #############################################################################
5
6 package LaTeX::Table;
7
8 use strict;
9 use warnings;
10
11 use Moose::Policy 'Moose::Policy::FollowPBP';
12 use Moose;
13
14 use version; our $VERSION = qv('0.9.15');
15
16 use LaTeX::Table::Types::Std;
17 use LaTeX::Table::Types::Xtab;
18 use LaTeX::Table::Types::Ctable;
19 use LaTeX::Table::Types::Longtable;
20
21 use Carp;
22 use Scalar::Util qw(reftype);
23 use English qw( -no_match_vars );
24
25 use Module::Pluggable
26 search_path => 'LaTeX::Table::Themes',
27 sub_name => 'themes',
28 except => 'LaTeX::Table::Themes::ThemeI',
29 instantiate => 'new';
30
31 for my $attr (
32 qw(label maincaption shortcaption caption caption_top coldef coldef_strategy
33 columns_like_header continued text_wrap header_sideways width maxwidth width_environment
34 custom_tabular_environment position fontsize fontfamily callback tabletail xentrystretch
35 resizebox sideways star _data_summary)
36 )
37 {
38 has $attr => ( is => 'rw', default => 0 );
39 }
40
41 has 'custom_template' => ( is => 'rw', isa => 'Str', default => 0 );
42 has 'filename' => ( is => 'rw', isa => 'Str', default => 'latextable.tex' );
43 has 'foottable' => ( is => 'rw', isa => 'Str', default => q{} );
44 has 'type' => ( is => 'rw', default => 'std' );
45 has '_type_obj' => ( is => 'rw' );
46 has 'header' => ( is => 'rw', default => sub { [] } );
47 has 'data' => ( is => 'rw', default => sub { [] } );
48 has 'environment' => ( is => 'rw', default => 1 );
49 has 'theme' => ( is => 'rw', default => 'Meyrin' );
50 has 'predef_themes' => ( is => 'rw', default => sub { {} } );
51 has 'custom_themes' => ( is => 'rw', default => sub { {} } );
52
53 for my $attr (qw(center left right _default_align)) {
54 has $attr => ( is => 'rw', isa => 'Bool', predicate => "has_$attr" );
55 }
56
57 has 'continuedmsg' => ( is => 'rw', default => '(continued)' );
58 has 'tabletailmsg' => ( is => 'rw', default => 'Continued on next page' );
59 has 'tableheadmsg' =>
60 ( is => 'rw', default => 'Continued from previous page' );
61
62 # deprecated
63 has 'table_environment' => ( is => 'rw', default => 'deprecated' );
64 has 'tabledef' => ( is => 'rw', default => 'deprecated' );
65 has 'tabledef_strategy' => ( is => 'rw', default => 'deprecated' );
66 has 'tablepos' => ( is => 'rw', default => 'deprecated' );
67 has 'size' => ( is => 'rw', default => 'deprecated' );
68
69 __PACKAGE__->meta->make_immutable;
70
71 ###########################################################################
72 # Usage : $table->generate_string();
73 # Purpose : generates LaTex data
74 # Returns : code
75 # Parameters : node
76 # Throws :
77 # Comments : n/a
78 # See also :
79
80 sub generate_string {
81 my ( $self, @args ) = @_;
82
83 # support for < 0.9.3 API
84 $self->_compatibility_layer(@args);
85
86 # are the user provided options ok?
87 $self->_check_options();
88
89 # analyze the data
90 $self->_calc_data_summary( $self->get_data );
91
92 if ( $self->get_type eq 'xtab' ) {
93 $self->set__type_obj(
94 LaTeX::Table::Types::Xtab->new( _table_obj => $self ) );
95 }
96 elsif ( $self->get_type eq 'longtable' ) {
97 $self->set__type_obj(
98 LaTeX::Table::Types::Longtable->new( _table_obj => $self ) );
99 }
100 elsif ( $self->get_type eq 'ctable' ) {
101 $self->set__type_obj(
102 LaTeX::Table::Types::Ctable->new( _table_obj => $self ) );
103 }
104 else {
105 $self->set__type_obj(
106 LaTeX::Table::Types::Std->new( _table_obj => $self ) );
107 }
108
109 my $code = $self->get__type_obj->generate_latex_code( $self->get_header,
110 $self->get_data );
111
112 return $code;
113 }
114
115 sub _load_themes {
116 my ($self) = @_;
117 my %defs;
118
119 for my $theme_obj ( $self->themes ) {
120 %defs = ( %defs, %{ $theme_obj->_definition } );
121 }
122 $self->set_predef_themes( \%defs );
123 return;
124 }
125
126 sub _compatibility_layer {
127 my ( $self, @args ) = @_;
128 if ( $self->get_tablepos ne 'deprecated' ) {
129 carp('DEPRECATED: Use position instead of tablepos.');
130 $self->set_position( $self->get_tablepos );
131 }
132 if ( $self->get_table_environment ne 'deprecated' ) {
133 carp('DEPRECATED: Use environment instead of table_environment.');
134 $self->set_environment( $self->get_table_environment );
135 }
136 if ( $self->get_tabledef ne 'deprecated' ) {
137 carp('DEPRECATED: Use coldef instead of tabledef.');
138 $self->set_coldef( $self->get_tabledef );
139 }
140 if ( $self->get_tabledef_strategy ne 'deprecated' ) {
141 carp('DEPRECATED: Use coldef_strategy instead of tabledef_strategy.');
142 $self->set_coldef_strategy( $self->get_tabledef_strategy );
143 }
144 if ( $self->get_size ne 'deprecated' ) {
145 carp('DEPRECATED: size was renamed to fontsize.');
146 $self->set_fontsize( $self->get_size );
147 }
148 my $cs = $self->get_coldef_strategy();
149
150 if ( $cs && defined reftype $cs && reftype $cs eq 'HASH' ) {
151 if ( defined $cs->{'DEFAULT'} ) {
152 carp( 'DEPRECATED: DEFAULT in coldef_strategy was renamed to '
153 . 'DEFAULT_COL.' );
154 $cs->{'DEFAULT_COL'} = $cs->{'DEFAULT'};
155 delete $cs->{'DEFAULT'};
156 }
157 if ( defined $cs->{'DEFAULT_X'} ) {
158 carp( 'DEPRECATED: DEFAULT_X in coldef_strategy was renamed to '
159 . 'DEFAULT_COL_X.' );
160 $cs->{'DEFAULT_COL_X'} = $cs->{'DEFAULT_X'};
161 delete $cs->{'DEFAULT_X'};
162 }
163 if ( defined $cs->{'IS_A_NUMBER'} ) {
164 carp( 'DEPRECATED: IS_A_NUMBER in coldef_strategy was renamed to '
165 . 'NUMBER.' );
166 $cs->{'NUMBER'} = $cs->{'IS_A_NUMBER'};
167 delete $cs->{'IS_A_NUMBER'};
168 }
169 if ( defined $cs->{'IS_LONG'} ) {
170 carp( 'DEPRECATED: IS_LONG in coldef_strategy was renamed to '
171 . 'LONG and is now a regex. Converting it.' );
172 $cs->{'LONG'} = qr{\A \s* .{$cs->{'IS_LONG'},}? \s* \z}xms;
173 delete $cs->{'IS_LONG'};
174 }
175 $self->set_coldef_strategy($cs);
176 }
177 return if !defined $args[0];
178 if ( reftype $args[0] eq 'ARRAY' ) {
179 carp('DEPRECATED. Use options header and data instead.');
180 $self->set_header( $args[0] );
181 if ( reftype $args[1] eq 'ARRAY' ) {
182 $self->set_data( $args[1] );
183 }
184 }
185 return;
186 }
187
188 sub _row_is_latex_command {
189 my ( $self, $row ) = @_;
190 if ( scalar( @{$row} ) == 1 && $row->[0] =~ m{\A \s* \\ }xms ) {
191 return 1;
192 }
193 return 0;
194 }
195
196 sub invalid_option_usage {
197 my ( $self, $option, $msg ) = @_;
198 croak "Invalid usage of option $option: $msg.";
199 }
200
201 sub _check_options {
202 my ($self) = @_;
203
204 # default floating enviromnent is table
205 if ( $self->get_environment eq '1' ) {
206 $self->set_environment('table');
207 }
208
209 # check header and data
210 $self->_check_2d_array( $self->get_header, 'header' );
211 $self->_check_2d_array( $self->get_data, 'data' );
212
213 if ( $self->get_callback && reftype $self->get_callback ne 'CODE' ) {
214 $self->invalid_option_usage( 'callback', 'Not a code reference' );
215 }
216 if ( $self->get_columns_like_header ) {
217 $self->_check_1d_array( $self->get_columns_like_header,
218 q{}, 'columns_like_header' );
219 }
220 if ( $self->get_resizebox ) {
221 $self->_check_1d_array( $self->get_resizebox, q{}, 'resizebox' );
222 }
223 if ( $self->get_type eq 'xtab' && !$self->get_environment ) {
224 $self->invalid_option_usage( 'environment',
225 'xtab requires an environment' );
226 }
227 if ( $self->get_type eq 'xtab' && $self->get_position ) {
228 $self->invalid_option_usage( 'position',
229 'xtab does not support position' );
230 }
231
232 # handle default values by ourselves
233 if ( $self->get_width_environment eq 'tabular*' ) {
234 $self->set_width_environment(0);
235 }
236
237 $self->_check_align;
238
239 if ( $self->get_maincaption && $self->get_shortcaption ) {
240 $self->invalid_option_usage( 'maincaption, shortcaption',
241 'only one allowed.' );
242 }
243 if ( !$self->get_width && $self->get_type ne 'longtable' && $self->get_width_environment eq 'tabularx' ) {
244 $self->invalid_option_usage( 'width_environment',
245 'Is tabularx and width is unset' );
246 }
247 if ( !$self->get_width && $self->get_width_environment eq 'tabulary' ) {
248 $self->invalid_option_usage( 'width_environment',
249 'Is tabulary and width is unset' );
250 }
251 return;
252 }
253
254 sub _check_align {
255 my ($self) = @_;
256 my $cnt_def_alignments = 0;
257 my $cnt_true_alignments = 0;
258
259 if ( $self->has_center ) {
260 $cnt_def_alignments++;
261 }
262 if ( $self->has_right ) {
263 $cnt_def_alignments++;
264 }
265 if ( $self->has_left ) {
266 $cnt_def_alignments++;
267 }
268 if ( $self->get_center ) {
269 $cnt_true_alignments++;
270 }
271 if ( $self->get_right ) {
272 $cnt_true_alignments++;
273 }
274 if ( $self->get_left ) {
275 $cnt_true_alignments++;
276 }
277
278 if ( $cnt_true_alignments > 1 ) {
279 $self->invalid_option_usage( 'center, left, right',
280 'only one allowed.' );
281 }
282 if ( $cnt_def_alignments == 0 ) {
283 $self->set__default_align(1);
284 }
285 else {
286 $self->set__default_align(0);
287 }
288 return;
289 }
290
291 sub _apply_callback {
292 my ( $self, $i, $j, $value, $is_header ) = @_;
293 my $col_cb = $self->_get_mc_def($value);
294 $col_cb->{value}
295 = &{ $self->get_callback }( $i, $j, $col_cb->{value}, $is_header );
296 return $self->_get_mc_value($col_cb);
297 }
298
299 sub _examine_data {
300 my ($self) = @_;
301 my $text_wrap = $self->get_text_wrap;
302 my @data = @{ $self->get_data };
303 if ( $self->get_callback ) {
304 for my $i ( 0 .. $#data ) {
305 my @row = @{ $data[$i] };
306 my $k = 0;
307 for my $j ( 0 .. ( scalar @{ $data[$i] } - 1 ) ) {
308 $row[$j] = $self->_apply_callback( $i, $k, $data[$i][$j], 0 );
309 $k += $self->_extract_number_columns( $data[$i][$j] );
310 }
311 $data[$i] = \@row;
312 }
313 }
314 return @data
315 }
316
317 sub _ioerror {
318 my ( $self, $function, $error ) = @_;
319 croak "IO error: Can't $function '" . $self->get_filename . "': $error";
320 }
321
322 sub generate {
323 my ( $self, $header, $data ) = @_;
324 my $code = $self->generate_string( $header, $data );
325 open my $LATEX, '>', $self->get_filename
326 or $self->_ioerror( 'open', $OS_ERROR );
327 print {$LATEX} $code
328 or $self->_ioerror( 'write', $OS_ERROR );
329 close $LATEX
330 or $self->_ioerror( 'close', $OS_ERROR );
331 return 1;
332 }
333
334 sub _default_coldef_strategy {
335 my ($self) = @_;
336 my $STRATEGY = {
337 MISSING_VALUE => qr{\A \s* \z}xms,
338 NUMBER =>
339 qr{\A\s*([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?\s*\z}xms,
340 NUMBER_MUST_MATCH_ALL => 1,
341 LONG => qr{\A \s* (?=\w+\s+\w+).{29,}? \S}xms,
342 LONG_MUST_MATCH_ALL => 0,
343 NUMBER_COL => 'r',
344 NUMBER_COL_X => 'r',
345 LONG_COL => 'p{5cm}',
346 LONG_COL_X => 'X',
347 LONG_COL_Y => 'L',
348 DEFAULT_COL => 'l',
349 DEFAULT_COL_X => 'l',
350 };
351 $self->set_coldef_strategy($STRATEGY);
352 return $STRATEGY;
353 }
354
355 sub _check_coldef_strategy {
356 my ( $self, $strategy ) = @_;
357 my $rt_strategy = reftype $strategy;
358 if ( !defined $rt_strategy || $rt_strategy ne 'HASH' ) {
359 $self->invalid_option_usage( 'coldef_strategy',
360 'Not a hash reference' );
361 }
362 my $default = $self->_default_coldef_strategy;
363 for my $key ( keys %{$default} ) {
364 if ( !defined $strategy->{$key} ) {
365 $strategy->{$key} = $default->{$key};
366 }
367 }
368
369 $self->set_coldef_strategy($strategy);
370
371 my @coltypes = $self->_get_coldef_types();
372 for my $type (@coltypes) {
373 if ( !defined $strategy->{"${type}_COL"} ) {
374 $self->invalid_option_usage( 'coldef_strategy',
375 "Missing column attribute ${type}_COL for $type" );
376 }
377 if ( !defined $strategy->{"${type}_MUST_MATCH_ALL"} ) {
378 $strategy->{"${type}_MUST_MATCH_ALL"} = 1;
379 }
380 }
381 return;
382 }
383
384 sub _extract_number_columns {
385 my ( $self, $col ) = @_;
386 my $def = $self->_get_mc_def($col);
387 if ( defined $def->{cols} ) {
388 return $def->{cols};
389 }
390 else {
391 return 1;
392 }
393 }
394
395 sub _get_coldef_types {
396 my ($self) = @_;
397
398 # everything that does not contain an underscore is a coltype
399 my @coltypes =
400 sort grep {m{ \A [^_]+ \z }xms} keys %{ $self->get_coldef_strategy };
401
402 return @coltypes;
403 }
404
405 sub _get_data_summary {
406 my ($self) = @_;
407 return @{ $self->get__data_summary() };
408 }
409
410 ###########################################################################
411 # Usage : $self->_get_data_summary(\@data);
412 # Purpose : find out how many columns we need and if column consists of
413 # numbers only
414 # Returns : an array with one entry for every column. Entry is either 1
415 # (column is numerical) or 0.
416 # Parameters : data columns
417 # Throws :
418 # Comments : n/a
419 # See also :
420
421 sub _calc_data_summary {
422 my ( $self, $data ) = @_;
423 my $max_col_number = 0;
424 my $strategy = $self->get_coldef_strategy;
425 if ( !$strategy ) {
426 $strategy = $self->_default_coldef_strategy;
427 }
428 else {
429 $self->_check_coldef_strategy($strategy);
430 }
431 my %matches;
432 my %cells;
433
434 my @coltypes = $self->_get_coldef_types();
435
436 ROW:
437 for my $row ( @{$data} ) {
438 if ( scalar @{$row} == 0 || $self->_row_is_latex_command($row) ) {
439 next ROW;
440 }
441 if ( scalar @{$row} > $max_col_number ) {
442 $max_col_number = scalar @{$row};
443 }
444 my $i = 0;
445 COL:
446 for my $col ( @{$row} ) {
447 next COL if $col =~ $strategy->{MISSING_VALUE};
448
449 for my $coltype (@coltypes) {
450 if ( $col =~ $strategy->{$coltype} ) {
451 $matches{$i}{$coltype}++;
452 }
453 }
454 $cells{$i}++;
455 $i += $self->_extract_number_columns($col);
456 }
457 }
458 my @summary;
459 for my $i ( 0 .. $max_col_number - 1 ) {
460 my $type_of_this_col = 'DEFAULT';
461 for my $coltype (@coltypes) {
462 if (defined $matches{$i}{$coltype}
463 && ( !$strategy->{"${coltype}_MUST_MATCH_ALL"}
464 || $cells{$i} == $matches{$i}{$coltype} )
465 )
466 {
467 $type_of_this_col = $coltype;
468 }
469 }
470 push @summary, $type_of_this_col;
471 }
472 $self->set__data_summary( \@summary );
473 return;
474 }
475
476 sub _apply_header_formatting {
477 my ( $self, $col, $aligning ) = @_;
478 my $theme = $self->get_theme_settings;
479 if ( $aligning
480 && defined $theme->{'HEADER_CENTERED'}
481 && $theme->{'HEADER_CENTERED'} )
482 {
483 $col = $self->_add_mc_def(
484 { value => $col, align => 'c', cols => '1' } );
485 }
486 if ( length $col ) {
487 if ( defined $theme->{'HEADER_FONT_STYLE'} ) {
488 $col = $self->_add_font_family( $col,
489 $theme->{'HEADER_FONT_STYLE'} );
490 }
491 if ( defined $theme->{'HEADER_FONT_COLOR'} ) {
492 $col = $self->_add_font_color( $col,
493 $theme->{'HEADER_FONT_COLOR'} );
494 }
495 }
496 return $col;
497 }
498
499 sub _get_cell_bg_color {
500 my ( $self, $row_bg_color, $col_id ) = @_;
501 my $cell_bg_color = $row_bg_color;
502 if ( $self->get_columns_like_header ) {
503 HEADER_COLUMN:
504 for my $i ( @{ $self->get_columns_like_header } ) {
505 if ( $i == $col_id ) {
506 $cell_bg_color
507 = $self->get_theme_settings->{'HEADER_BG_COLOR'};
508 last HEADER_COLUMN;
509 }
510 }
511 }
512 return $cell_bg_color;
513 }
514
515 ###########################################################################
516 # Usage : $self->_get_row_code($cols_ref);
517 # Purpose : generate the LaTeX code of a row
518 # Returns : LaTeX code
519 # Parameters : the columns
520 # Throws :
521 # Comments : n/a
522 # See also :
523
524 sub _get_row_array {
525 my ( $self, $cols_ref, $bgcolor, $is_header ) = @_;
526 my @cols_defs = map { $self->_get_mc_def($_) } @{$cols_ref};
527 my @cols = ();
528 my $theme = $self->get_theme_settings;
529 my $vlines = $theme->{'VERTICAL_RULES'};
530 my $v0 = q{|} x $vlines->[0];
531 my $v1 = q{|} x $vlines->[1];
532 my $v2 = q{|} x $vlines->[2];
533 my $j = 0;
534 my $col_id = 0;
535 for my $col_def (@cols_defs) {
536 if ( !$is_header && $self->get_columns_like_header ) {
537 HEADER_COLUMN:
538 for my $i ( @{ $self->get_columns_like_header } ) {
539 next HEADER_COLUMN if $i != $col_id;
540 $col_def = $self->_get_mc_def(
541 $self->_apply_header_formatting(
542 $self->_get_mc_value($col_def), 0
543 )
544 );
545 if ( !defined $col_def->{cols} ) {
546 my @summary = $self->_get_data_summary();
547 $col_def->{cols} = 1;
548 $col_def->{align}
549 = $self->get_coldef_strategy->{ $summary[$col_id]
550 . $self->_get_coldef_type_col_suffix };
551 }
552 }
553 }
554 if ( defined $col_def->{cols} ) {
555 my $vl_pre = q{};
556 my $vl_post = q{};
557
558 if ( $j == 0 ) {
559 $vl_pre = $v0;
560 }
561
562 if ( $j == ( scalar(@cols_defs) - 1 ) ) {
563 $vl_post = $v0;
564 }
565 elsif ( $j == 0 && $col_def->{cols} == 1 ) {
566 $vl_post = $v1;
567 }
568 else {
569 $vl_post = $v2;
570 }
571
572 my $color_code = q{};
573
574 my $cell_bg_color
575 = $self->_get_cell_bg_color( $bgcolor, $col_id );
576 if ( defined $cell_bg_color ) {
577 $color_code = '>{\columncolor{' . $cell_bg_color . '}}';
578 }
579
580 push @cols,
581 '\\multicolumn{'
582 . $col_def->{cols} . '}{'
583 . $vl_pre
584 . $color_code
585 . $col_def->{align}
586 . $vl_post . '}{'
587 . $col_def->{value} . '}';
588
589 $col_id += $col_def->{cols};
590 }
591 else {
592 push @cols, $col_def->{value};
593 $col_id++;
594 }
595 $j++;
596 }
597 if ( defined $bgcolor ) {
598
599 # @cols has always at least one element, otherwise we draw a line
600 $cols[0] = "\\rowcolor{$bgcolor}" . $cols[0];
601 }
602 return \@cols;
603 }
604
605 sub _get_row_code {
606 my ( $self, $cols_ref, $bgcolor, $is_header ) = @_;
607 my $cols = $self->_get_row_array( $cols_ref, $bgcolor, $is_header );
608 return join( ' & ', @{$cols} ) . "\\\\\n";
609 }
610
611 sub _add_mc_def {
612 my ( $self, $arg_ref ) = @_;
613 my $def = $self->_get_mc_def( $arg_ref->{value} );
614 if ( defined $def->{cols} ) {
615 return $arg_ref->{value};
616 }
617 else {
618 return $self->_get_mc_value($arg_ref);
619 }
620 }
621
622 sub _get_mc_value {
623 my ( $self, $def ) = @_;
624 if ( defined $def->{cols} ) {
625 return $def->{value} . q{:} . $def->{cols} . $def->{align};
626 }
627 else {
628 return $def->{value};
629 }
630 }
631
632 sub _get_mc_def {
633 my ( $self, $value ) = @_;
634 if ( $value =~ m{ \A (.*)\:(\d)([clr]) \z }xms ) {
635 return { value => $1, cols => $2, align => $3 };
636 }
637 else {
638 return { value => $value };
639 }
640 }
641
642 ###############################################################################
643 # Usage : $self->_add_font_family($col, 'bf');
644 # Purpose : add font family to column value
645 # Returns : new column value
646 # Parameters : column value and family (tt, bf, it, sc)
647 # Throws : exception when family is not known
648
649 sub _add_font_family {
650 my ( $self, $col, $family ) = @_;
651 my %know_families = ( tt => 1, bf => 1, it => 1, sc => 1 );
652 if ( !defined $know_families{$family} ) {
653 $self->invalid_option_usage(
654 'custom_themes',
655 "Family not known: $family. Valid families are: " . join ', ',
656 sort keys %know_families
657 );
658 }
659 my $col_def = $self->_get_mc_def($col);
660 $col_def->{value} = "\\text$family" . '{' . $col_def->{value} . '}';
661 return $self->_get_mc_value($col_def);
662 }
663
664 ###############################################################################
665 # Usage : $self->_add_font_color($col, $color);
666 # Purpose : add font color to column value
667 # Returns : new column value
668 # Parameters : column value and color
669
670 sub _add_font_color {
671 my ( $self, $col, $color ) = @_;
672 my $col_def = $self->_get_mc_def($col);
673 $col_def->{value} = "\\color{$color}" . $col_def->{value};
674 return $self->_get_mc_value($col_def);
675 }
676
677 sub _get_coldef_type_col_suffix {
678 my ($self) = @_;
679 if ( $self->get_width_environment eq 'tabularx'
680 || $self->get_type eq 'ctable' )
681 {
682 return '_COL_X';
683 }
684 if ( $self->get_width_environment eq 'tabulary' ) {
685 return '_COL_Y';
686 }
687 return '_COL';
688 }
689
690 ###########################################################################
691 # Usage : $self->_get_coldef_code(\@data);
692 # Purpose : generate the LaTeX code of the column definitions (e.g.
693 # |l|r|r|r|)
694 # Returns : LaTeX code
695 # Parameters : the data columns
696 # Comments : Tries to be intelligent. Hope it is ;)
697
698 sub _get_coldef_code {
699 my ( $self, $data ) = @_;
700 my @cols = $self->_get_data_summary();
701 my $vlines = $self->get_theme_settings->{'VERTICAL_RULES'};
702
703 my $v0 = q{|} x $vlines->[0];
704 my $v1 = q{|} x $vlines->[1];
705 my $v2 = q{|} x $vlines->[2];
706
707 my $table_def = q{};
708 my $i = 0;
709 my $strategy = $self->get_coldef_strategy();
710 my $typesuffix = $self->_get_coldef_type_col_suffix();
711
712 my @attributes = grep {m{ _COL }xms} keys %{$strategy};
713
714 for my $col (@cols) {
715
716 # align text right, numbers left, first col always left
717 my $align;
718
719 for my $attribute ( sort @attributes ) {
720 if ( $attribute =~ m{ \A $col $typesuffix \z }xms ) {
721 $align = $strategy->{$attribute};
722
723 # for _X and _Y, use default if no special defs are found
724 }
725 elsif ( ( $typesuffix eq '_COL_X' || $typesuffix eq '_COL_Y' )
726 && $attribute =~ m{ \A $col _COL \z }xms )
727 {
728 $align = $strategy->{$attribute};
729 }
730 }
731
732 if ( $i == 0 ) {
733 if ( defined $self->get_theme_settings->{'STUB_ALIGN'} ) {
734 $align = $self->get_theme_settings->{'STUB_ALIGN'};
735 }
736 $table_def .= $v0 . $align . $v1;
737 }
738 elsif ( $i == ( scalar(@cols) - 1 ) ) {
739 $table_def .= $align . $v0;
740 }
741 else {
742 $table_def .= $align . $v2;
743 }
744 $i++;
745 if ( $i == 1
746 && $self->get_width
747 && !$self->get_width_environment
748 && $self->get_type ne 'ctable' )
749 {
750 $table_def .= '@{\extracolsep{\fill}}';
751 }
752 }
753 return $table_def;
754 }
755
756 ###########################################################################
757 # Usage : $self->get_theme_settings();
758 # Purpose : return an hash reference with all settings of the current
759 # theme
760 # Returns : see purpose
761 # Parameters : none
762 # Throws : exception if theme is unknown
763 # See also : get_available_themes();
764
765 sub get_theme_settings {
766 my ($self) = @_;
767
768 my $themes = $self->get_available_themes();
769 if ( defined $themes->{ $self->get_theme } ) {
770 return $themes->{ $self->get_theme };
771 }
772 $self->invalid_option_usage( 'theme', 'Not known: ' . $self->get_theme );
773 return;
774 }
775
776 sub _check_1d_array {
777 my ( $self, $arr_ref_1d, $desc, $option ) = @_;
778 if ( !defined reftype $arr_ref_1d || reftype $arr_ref_1d ne 'ARRAY' ) {
779 $self->invalid_option_usage( $option,
780 "${desc}Not an array reference" );
781 }
782 return;
783 }
784
785 sub _check_2d_array {
786 my ( $self, $arr_ref_2d, $desc ) = @_;
787 $self->_check_1d_array( $arr_ref_2d, q{}, $desc );
788 my $i = 0;
789 for my $arr_ref ( @{$arr_ref_2d} ) {
790 $self->_check_1d_array( $arr_ref, "$desc\[$i\] ", $desc );
791 my $j = 0;
792 for my $scalar ( @{$arr_ref} ) {
793 my $rt_scalar = reftype $scalar;
794 if ( defined $rt_scalar ) {
795 $self->invalid_option_usage( $desc,
796 "$desc\[$i\]\[$j\] not a scalar" );
797 }
798 if ( !defined $scalar ) {
799 $self->invalid_option_usage( $desc,
800 "Undefined value in $desc\[$i\]\[$j\]" );
801 }
802 $j++;
803 }
804 $i++;
805 }
806 return;
807 }
808
809 ###########################################################################
810 # Usage : $self->get_available_themes();
811 # Purpose : return an hash reference with all available themes
812 # (predefined and custom)
813 # Returns : see purpose
814 # Parameters : none
815 # Throws : no exceptions
816 # See also : get_theme_settings()
817
818 sub get_available_themes {
819 my ($self) = @_;
820 $self->_load_themes();
821 return {
822 ( %{ $self->get_predef_themes }, %{ $self->get_custom_themes } ) };
823 }
824
825 no Moose;
826 1; # Magic true value required at end of module
827 __END__
828
829 =head1 NAME
830
831 LaTeX::Table - Perl extension for the automatic generation of LaTeX tables.
832
833 =head1 VERSION
834
835 This document describes LaTeX::Table version 0.9.15
836
837 =head1 SYNOPSIS
838
839 use LaTeX::Table;
840 use Number::Format qw(:subs); # use mighty CPAN to format values
841
842 my $header = [
843 [ 'Item:2c', '' ],
844 [ '\cmidrule(r){1-2}' ],
845 [ 'Animal', 'Description', 'Price' ],
846 ];
847
848 my $data = [
849 [ 'Gnat', 'per gram', '13.65' ],
850 [ '', 'each', '0.0173' ],
851 [ 'Gnu', 'stuffed', '92.59' ],
852 [ 'Emu', 'stuffed', '33.33' ],
853 [ 'Armadillo', 'frozen', '8.99' ],
854 ];
855
856 my $table = LaTeX::Table->new(
857 {
858 filename => 'prices.tex',
859 maincaption => 'Price List',
860 caption => 'Try our special offer today!',
861 label => 'table:prices',
862 position => 'htb',
863 header => $header,
864 data => $data,
865 }
866 );
867
868 # write LaTeX code in prices.tex
869 $table->generate();
870
871 # callback functions help you to format values easily (as
872 # a great alternative to LaTeX packages like rccol)
873 #
874 # Here, the first colum and the header is printed in upper
875 # case and the third colum is formatted with format_price()
876 $table->set_callback(sub {
877 my ($row, $col, $value, $is_header ) = @_;
878 if ($col == 0 || $is_header) {
879 $value = uc $value;
880 }
881 elsif ($col == 2 && !$is_header) {
882 $value = format_price($value, 2, '');
883 }
884 return $value;
885 });
886
887 print $table->generate_string();
888
889 Now in your LaTeX document:
890
891 \documentclass{article}
892
893 % for multipage tables (xtab or longtable)
894 \usepackage{xtab}
895 %\usepackage{longtable}
896
897 % for publication quality tables (Meyrin theme, the default)
898 \usepackage{booktabs}
899 % for the NYC theme
900 \usepackage{array}
901 \usepackage{colortbl}
902 \usepackage{xcolor}
903
904 \begin{document}
905 \input{prices}
906 \end{document}
907
908 =head1 DESCRIPTION
909
910 LaTeX makes professional typesetting easy. Unfortunately, this is not entirely
911 true for tables and the standard LaTeX table macros have a rather limited
912 functionality. This module supports many CTAN packages and hides the
913 complexity of using them behind an easy and intuitive API.
914
915 =head1 FEATURES
916
917 This module supports multipage tables via the C<xtab> or the C<longtable>
918 package. For publication quality tables, it uses the C<booktabs> package. It
919 also supports the C<tabularx> and C<tabulary> packages for nicer fixed-width
920 tables. Furthermore, it supports the C<colortbl> package for colored tables
921 optimized for presentations. The powerful new C<ctable> package is supported
922 and especially recommended when footnotes are needed. C<LaTeX::Table> ships
923 with some predefined, good looking L<"THEMES">. The program I<ltpretty> makes
924 it possible to use this module from within a text editor.
925
926 =head1 INTERFACE
927
928 =over
929
930 =item C<my $table = LaTeX::Table-E<gt>new($arg_ref)>
931
932 Constructs a C<LaTeX::Table> object. The parameter is an hash reference with
933 options (see below).
934
935 =item C<$table-E<gt>generate()>
936
937 Generates the LaTeX table code. The generated LaTeX table can be included in
938 a LaTeX document with the C<\input> command:
939
940 % include prices.tex, generated by LaTeX::Table
941 \input{prices}
942
943 =item C<$table-E<gt>generate_string()>
944
945 Same as generate() but instead of creating a LaTeX file, this returns the LaTeX code
946 as string.
947
948 my $latexcode = $table->generate_string();
949
950 =item C<$table-E<gt>get_available_themes()>
951
952 Returns an hash reference to all available themes. See L<"THEMES"> for
953 details.
954
955 for my $theme ( keys %{ $table->get_available_themes } ) {
956 ...
957 }
958
959 =item C<$table-E<gt>search_path( add =E<gt> "MyThemes" );>
960
961 C<LaTeX::Table> will search under the C<LaTeX::Table::Themes::> namespace for
962 themes. You can add here an additional search path. Inherited from
963 L<Module::Pluggable>.
964
965 =back
966
967 =head1 OPTIONS
968
969 Options can be defined in the constructor hash reference or with the setter
970 C<set_optionname>. Additionally, getters of the form C<get_optionname> are
971 created.
972
973 =head2 BASIC OPTIONS
974
975 =over
976
977 =item C<filename>
978
979 The name of the LaTeX output file. Default is 'latextable.tex'.
980
981 =item C<type>
982
983 Can be 'std' for standard LaTeX tables, 'ctable' for tables using the
984 C<ctable> package or 'xtab' and 'longtable' for multipage tables
985 (requires the C<xtab> and C<longtable> LaTeX
986 packages, respectively).
987
988 =item C<header>
989
990 The header. It is a reference to an array (the rows) of array references (the
991 columns).
992
993 $table->set_header([ [ 'Animal', 'Price' ] ]);
994
995 will produce following header:
996
997 +--------+-------+
998 | Animal | Price |
999 +--------+-------+
1000
1001 Here an example for a multirow header:
1002
1003 $table->set_header([ [ 'Animal', 'Price' ], ['', '(roughly)' ] ]);
1004
1005 This code will produce this header:
1006
1007 +--------+-----------+
1008 | Animal | Price |
1009 | | (roughly) |
1010 +--------+-----------+
1011
1012 Single column rows that start with a backslash are treated as LaTeX commands
1013 and are not further formatted. So,
1014
1015 my $header = [
1016 [ 'Item:2c', '' ],
1017 ['\cmidrule{1-2}'],
1018 [ 'Animal', 'Description', 'Price' ]
1019 ];
1020
1021 will produce following LaTeX code in the Zurich theme:
1022
1023 \multicolumn{2}{c}{\textbf{Item}} & \\
1024 \cmidrule{1-2}
1025 \textbf{Animal} & \multicolumn{1}{c}{\textbf{Description}} & \multicolumn{1}{c}{\textbf{Price}}\\
1026
1027 Note that there is no C<\multicolumn>, C<\textbf> or C<\\> added to the second row.
1028
1029 =item C<data>
1030
1031 The data. Once again a reference to an array (rows) of array references
1032 (columns).
1033
1034 $table->set_data([ [ 'Gnu', '92.59' ], [ 'Emu', '33.33' ] ]);
1035
1036 And you will get a table like this:
1037
1038 +-------+---------+
1039 | Gnu | 92.59 |
1040 | Emu | 33.33 |
1041 +-------+---------+
1042
1043 An empty column array will produce a horizontal rule (line):
1044
1045 $table->set_data([ [ 'Gnu', '92.59' ], [], [ 'Emu', '33.33' ] ]);
1046
1047 Now you will get such a table:
1048
1049 +-------+---------+
1050 | Gnu | 92.59 |
1051 +-------+---------+
1052 | Emu | 33.33 |
1053 +-------+---------+
1054
1055 This works also in C<header>.
1056
1057 Single column rows starting with a backslash are again printed without any
1058 formatting. So,
1059
1060 $table->set_data([ [ 'Gnu', '92.59' ], ['\hline'], [ 'Emu', '33.33' ] ]);
1061
1062 is equivalent to the example above (except that there always the correct rule
1063 command is used, i.e. C<\midrule> vs. C<\hline>).
1064
1065 =item C<custom_template>
1066
1067 The table types listed above use the L<Template> toolkit internally. These
1068 type tempates are very flexible and powerful, but you can also provide a
1069 custom template:
1070
1071 # Returns the header and data formatted in LaTeX code. Nothing else.
1072 $table->set_custom_template('[% HEADER_CODE %][% DATA_CODE %]');
1073
1074 See L<LaTeX::Table::Types::TypeI>.
1075
1076 =back
1077
1078 =head2 FLOATING TABLES
1079
1080 =over
1081
1082 =item C<environment>
1083
1084 If get_environment() returns a true value, then a floating environment will be
1085 generated. For I<std> tables, the default environment is 'table'. A true value different
1086 from '1' will be used as environment name. Default is 1 (use a 'table'
1087 environment).
1088
1089 The non-floating I<xtab> environment is mandatory (get_environment() must
1090 return a true value here) and supports all options in this section except
1091 for C<position>.
1092
1093 The I<ctable> type automatically adds an environment when any of the
1094 following options are set.
1095
1096 =item C<caption>
1097
1098 The caption of the table. Only generated if get_caption() returns a true value.
1099 Default is 0. Requires C<environment>.
1100
1101 =item C<caption_top>
1102
1103 If get_caption_top() returns a true value, then the caption is placed above the
1104 table. To use the standard caption command (C<\caption> in I<std> and
1105 I<longtable>, C<\topcaption> in I<xtab>) , use
1106
1107 ...
1108 caption_top => 1,
1109 ...
1110
1111 You can specify an alternative command here:
1112
1113 ...
1114 caption_top => 'topcaption', # would require the topcapt package
1115
1116 Or even multiple commands:
1117
1118 caption_top =>
1119 '\setlength{\abovecaptionskip}{0pt}\setlength{\belowcaptionskip}{10pt}\caption',
1120 ...
1121
1122 Default 0 (caption below the table) because the spacing in the standard LaTeX
1123 macros is optimized for bottom captions. At least for multipage tables,
1124 however, top captions are highly recommended. You can use the C<caption>
1125 LaTeX package to fix the spacing:
1126
1127 \usepackage[tableposition=top]{caption}
1128
1129 =item C<maincaption>
1130
1131 If get_maincaption() returns a true value, then this value will be displayed
1132 in the table listing (C<\listoftables>) and before the C<caption>. For example,
1133
1134 maincaption => 'Price List',
1135 caption => 'Try our special offer today!',
1136
1137 will generate
1138
1139 \caption[Price List]{Price List. Try our special offer today!}
1140
1141 Themes can set the font family of the maincaption.
1142
1143 Default 0. Requires C<environment>.
1144
1145 =item C<shortcaption>
1146
1147 Same as C<maincaption>, but does not appear in the caption, only in the table
1148 listing. Default 0. Requires C<environment>.
1149
1150 =item C<continued>
1151
1152 If true, then the table counter will be decremented by one and the
1153 C<continuedmsg> is appended to the caption. Useful for splitting tables. Default 0.
1154
1155 $table->set_continued(1);
1156
1157 =item C<continuedmsg>
1158
1159 If get_continued() returns a true value, then this text is appended to the
1160 caption. Default '(continued)'.
1161
1162 =item C<center>, C<right>, C<left>
1163
1164 Defines how the table is aligned in the available textwidth. Default is centered. Requires
1165 C<environment>. Only one of these options may return a true value.
1166
1167 # don't generate any aligning code
1168 $table->set_center(0);
1169
1170 =item C<label>
1171
1172 The label of the table. Only generated if get_label() returns a true value.
1173 Default is 0. Requires C<environment>.
1174
1175 $table->set_label('tbl:prices');
1176
1177 =item C<position>
1178
1179 The position of the environment, e.g. 'htb'. Only generated if get_position()
1180 returns a true value. Default 0. Requires C<environment> and tables of C<type>
1181 I<std>.
1182
1183 =item C<sideways>
1184
1185 Rotates the environment by 90 degrees. Default 0. For tables of C<type> I<std>
1186 and I<ctable>, this requires the C<rotating> LaTeX package, for I<xtab> or
1187 I<longtable> tables the C<lscape> package.
1188
1189 $table->set_sideways(1);
1190
1191 =item C<star>
1192
1193 Use the starred versions of the environments, which place the float over two
1194 columns when the C<twocolumn> option or the C<\twocolumn> command is active.
1195 Default 0.
1196
1197 $table->set_star(1);
1198
1199 =item C<fontfamily>
1200
1201 Valid values are 'rm' (Roman, serif), 'sf' (Sans-serif), 'tt' (Monospace or
1202 typewriter) and 0. Default is 0 (does not define a font family). Requires
1203 C<environment>.
1204
1205 =item C<fontsize>
1206
1207 Valid values are 'tiny', 'scriptsize', 'footnotesize', 'small', 'normal',
1208 'large', 'Large', 'LARGE', 'huge', 'Huge' and 0. Default is 0 (does not define
1209 a font size). Requires C<environment>.
1210
1211 =back
1212
1213 =head2 TABULAR ENVIRONMENT
1214
1215 =over
1216
1217 =item C<custom_tabular_environment>
1218
1219 If get_custom_tabular_environment() returns a true value, then this specified
1220 environment is used instead of the standard environments 'tabular' (I<std>)
1221 'longtable' (I<longtable>) or 'xtabular' (I<xtab>). For I<xtab> tables, you
1222 can also use the 'mpxtabular' environment here if you need footnotes. See the
1223 documentation of the C<xtab> package.
1224
1225 See also the documentation of C<width> below for cases when a width is
1226 specified.
1227
1228 =item C<coldef>
1229
1230 The table column definition, e.g. 'lrcr' which would result in:
1231
1232 \begin{tabular}{lrcr}
1233 ..
1234
1235 If unset, C<LaTeX::Table> tries to guess a good definition. Columns containing
1236 only numbers are right-justified, others left-justified. Columns with cells
1237 longer than 30 characters are I<p> (paragraph) columns of size '5cm' (I<X>
1238 columns when the C<tabularx>, I<L> when the C<tabulary> package is selected).
1239 These rules can be changed with set_coldef_strategy(). Default is 0 (guess
1240 good definition). The left-hand column, the stub, is normally exculded here
1241 and is always left aligned. See L<LaTeX::Table::Themes::ThemeI>.
1242
1243 =item C<coldef_strategy>
1244
1245 Controls the behaviour of the C<coldef> calculation when get_coldef()
1246 does not return a true value. It is a reference to a hash that contains
1247 regular expressions that define the I<types> of the columns. For example,
1248 the standard types I<NUMBER> and I<LONG> are defined as:
1249
1250 {
1251 NUMBER =>
1252 qr{\A\s*([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?\s*\z}xms,
1253 NUMBER_MUST_MATCH_ALL => 1,
1254 NUMBER_COL => 'r',
1255 LONG => qr{\A\s*(?=\w+\s+\w+).{29,}?\S}xms,
1256 LONG_MUST_MATCH_ALL => 0,
1257 LONG_COL => 'p{5cm}',
1258 LONG_COL_X => 'X',
1259 LONG_COL_Y => 'L',
1260 };
1261
1262 =over
1263
1264 =item C<TYPE =E<gt> $regex>
1265
1266 New types are defined with the regular expression C<$regex>. All B<cells> that
1267 match this regular expression have type I<TYPE>. A cell can have multiple
1268 types. The name of a type is not allowed to contain underscores (C<_>).
1269
1270 =item C<TYPE_MUST_MATCH_ALL>
1271
1272 This defines if whether a B<column> has type I<TYPE> when all B<cells>
1273 are of type I<TYPE> or at least one. Default is C<1> (C<$regex> must match
1274 all).
1275
1276 Note that columns can have only one type. Types are applied alphabetically,
1277 so for example a I<LONG> I<NUMBER> column has as final type I<NUMBER>.
1278
1279 =item C<TYPE_COL>
1280
1281 The C<coldef> attribute for I<TYPE> columns. Required (no default value).
1282
1283 =item C<TYPE_COL_X>, C<TYPE_COL_Y>
1284
1285 Same as C<TYPE_COL> but for C<tabularx> or C<tabulary> tables. If undefined,
1286 the attribute defined in C<TYPE_COL> is used.
1287
1288 =item C<DEFAULT_COL>, C<DEFAULT_COL_X>, C<DEFAULT_COL_Y>
1289
1290 The C<coldef> attribute for columns that do not match any specified type.
1291 Default 'l' (left-justified).
1292
1293 =item C<MISSING_VALUE>
1294
1295 Column values that match the specified regular expression are omitted in the
1296 C<coldef> calculation. Default is C<qr{\A \s* \z}xms>.
1297
1298 =back
1299
1300 Examples:
1301
1302 # change standard types
1303 $table->set_coldef_strategy({
1304 NUMBER => qr{\A \s* \d+ \s* \z}xms, # integers only
1305 LONG_COL => '>{\raggedright\arraybackslash}p{7cm}', # non-justified
1306 });
1307
1308 # add new types (here: columns that contain only URLs)
1309 $table->set_coldef_strategy({
1310 URL => qr{\A \s* http }xms,
1311 URL_COL => '>{\ttfamily}l',
1312 });
1313
1314
1315
1316 =item C<width>
1317
1318 If get_width() returns a true value, then C<LaTeX::Table> will use the starred
1319 version of the environment (e.g. C<tabular*> or C<xtabular*>) and will add the
1320 specified width as second parameter. It will also add
1321 C<@{\extracolsep{\fill}}> to the table column definition:
1322
1323 # use 75% of textwidth
1324 $table->set_width('0.75\textwidth');
1325
1326 This will produce following LaTeX code:
1327
1328 \begin{tabular*}{0.75\textwidth}{l@{\extracolsep{\fill} ... }
1329
1330 For tables of C<type> I<std>, it is also possible to use the C<tabularx> and
1331 C<tabulary> LaTeX packages (see C<width_environment> below). The tables of type I<ctable>
1332 automatically use the C<tabularx> package.
1333
1334 =item C<width_environment>
1335
1336 If get_width() (see above) returns a true value and table is of C<type> I<std>,
1337 then this option provides the possibility to add a custom tabular environment
1338 that supports a table width:
1339
1340 \begin{environment}{width}{def}
1341
1342 To use for example the one provided by the C<tabularx> LaTeX package, write:
1343
1344 # use the tabularx package (for a std table)
1345 $table->set_width('300pt');
1346 $table->set_width_environment('tabularx');
1347
1348 Note this will not add C<@{\extracolsep{\fill}}> and that this overwrites
1349 a C<custom_tabular_environment>.
1350
1351 It is possible to use C<tabularx> together with tables of type I<longtable>.
1352 In this case, you have to generate a I<file> and then load the table with the
1353 C<LTXtable> command (C<ltxtable> package):
1354
1355 $table = LaTeX::Table->new(
1356 { header => $header,
1357 data => $data,
1358 filename => 'mylongtable.tex'
1359 type => 'longtable',
1360 ...
1361 center => 0,
1362 width_environment => 'tabularx',
1363 }
1364 );
1365
1366 Then in LaTeX:
1367
1368 \begin{center}
1369 \LTXtable{0.8\textwidth}{mylongtable}
1370 \end{center}
1371
1372 Note that we have to do the centering and specification of the width in LaTeX.
1373
1374 Default is 0 (see C<width>).
1375
1376 =item C<maxwidth>
1377
1378 Only supported by tables of type I<ctable>.
1379
1380 =item C<callback>
1381
1382 If get_callback() returns a true value and the return value is a code reference,
1383 then this callback function will be called for every column in C<header>
1384 and C<data>. The return value of this function is then printed instead of the
1385 column value.
1386
1387 The passed arguments are C<$row>, C<$col> (both starting with 0), C<$value> and
1388 C<$is_header>.
1389
1390 use LaTeX::Encode;
1391 use Number::Format qw(:subs);
1392 ...
1393
1394 # use LaTeX::Encode to encode LaTeX special characters,
1395 # format the third column with Format::Number (only the data)
1396 my $table = LaTeX::Table->new(
1397 { header => $header,
1398 data => $data,
1399 callback => sub {
1400 my ( $row, $col, $value, $is_header ) = @_;
1401 if ( $col == 2 && !$is_header ) {
1402 $value = format_price($value, 2, '');
1403 }
1404 else {
1405 $value = latex_encode($value);
1406 }
1407 return $value;
1408 },
1409 }
1410 );
1411
1412 =item C<foottable>
1413
1414 Only supported by tables of type C<ctable>. The footnote C<\tnote> commands.
1415 See the documentation of the C<ctable> LaTeX package.
1416
1417 $table->set_foottable('\tnote{footnotes are placed under the table}');
1418
1419 =item C<resizebox>
1420
1421 If get_resizebox() returns a true value, then the resizebox command is used to
1422 resize the table. Takes as argument a reference to an array. The first element
1423 is the desired width. If a second element is not given, then the hight is set to
1424 a value so that the aspect ratio is still the same. Requires the C<graphicx>
1425 LaTeX package. Default 0.
1426
1427 $table->set_resizebox([ '0.6\textwidth' ]);
1428
1429 $table->set_resizebox([ '300pt', '200pt' ]);
1430
1431
1432 =back
1433
1434 =head2 MULTIPAGE TABLES
1435
1436 =over
1437
1438 =item C<tableheadmsg>
1439
1440 When get_caption_top() and get_tableheadmsg() both return true values, then
1441 additional captions are printed on the continued pages. Default caption text
1442 is 'Continued from previous page'.
1443
1444 =item C<tabletailmsg>
1445
1446 Message at the end of a multipage table. Default is 'Continued on next page'.
1447 When using C<caption_top>, this is in most cases unnecessary and it is
1448 recommended to omit the tabletail (see below).
1449
1450 =item C<tabletail>
1451
1452 Custom table tail. Default is multicolumn with the tabletailmsg (see above)
1453 right-justified.
1454
1455 # don't add any tabletail code:
1456 $table->set_tabletail(q{});
1457
1458 =item C<xentrystretch>
1459
1460 Option for xtab. Play with this option if the number of rows per page is not
1461 optimal. Requires a number as parameter. Default is 0 (does not use this option).
1462
1463 $table->set_xentrystretch(-0.1);
1464
1465 =back
1466
1467 =head2 THEMES
1468
1469 =over
1470
1471 =item C<theme>
1472
1473 The name of the theme. Default is I<Meyrin> (requires C<booktabs> LaTeX
1474 package).
1475
1476 See L<LaTeX::Table::Themes::ThemeI> how to define custom themes.
1477
1478 The themes are defined in L<LaTeX::Table::Themes::Beamer>,
1479 L<LaTeX::Table::Themes::Booktabs>, L<LaTeX::Table::Themes::Classic>,
1480 L<LaTeX::Table::Themes::Modern>.
1481
1482 $table->set_theme('Zurich');
1483
1484 =item C<predef_themes>
1485
1486 All predefined themes. Getter only.
1487
1488 =item C<custom_themes>
1489
1490 All custom themes. See L<LaTeX::Table::Themes::ThemeI>.
1491
1492 =item C<columns_like_header>
1493
1494 Takes as argument a reference to an array with column ids (again, starting
1495 with 0). These columns are formatted like header columns.
1496
1497 # a "transposed" table ...
1498 my $table = LaTeX::Table->new(
1499 { data => $data,
1500 columns_like_header => [ 0 ], }
1501 );
1502
1503 =item C<header_sideways>
1504
1505 If get_header_sideways() returns a true value, then the header columns will
1506 be rotated by 90 degrees. Requires the C<rotating> LaTeX package. Does not
1507 affect data columns specified in columns_like_header(). If you do not want to
1508 rotate all headers, use a callback function B<instead>:
1509
1510 ...
1511 header_sideways => 0,
1512 callback => sub {
1513 my ( $row, $col, $value, $is_header ) = @_;
1514 if ( $col != 0 && $is_header ) {
1515 $value = '\begin{sideways}' . $value . '\end{sideways}';
1516 }
1517 return $value;
1518 }
1519 ...
1520
1521 =back
1522
1523 =head1 MULTICOLUMNS
1524
1525 Multicolumns are defined in LaTeX with
1526 C<\multicolumn{$cols}{$alignment}{$text}>. This module supports a simple
1527 shortcut of the format C<$text:$cols$alignment>. For example, C<Item:2c> is
1528 equivalent to C<\multicolumn{2}{c}{Item}>. Note that vertical rules (C<|>) are
1529 automatically added here according the rules settings in the theme. See
1530 L<LaTeX::Table::Themes::ThemeI>. C<LaTeX::Table> also uses this shortcut to
1531 determine the column ids. So in this example,
1532
1533 my $data = [ [' \multicolumn{2}{c}{A}', 'B' ], [ 'C:2c', 'D' ] ];
1534
1535 'B' would have an column id of 1 and 'D' 2 ('A' and 'C' both 0). This is important
1536 for callback functions and for the coldef calculation.
1537 See L<"TABULAR ENVIRONMENT">.
1538
1539 =head1 EXAMPLES
1540
1541 See I<examples/examples.pdf> in this distribution for a short tutorial that
1542 covers the main features of this module. See also the example application
1543 I<csv2pdf> for an example of the common task of converting a CSV (or Excel)
1544 file to LaTeX or even PDF.
1545
1546 =head1 DIAGNOSTICS
1547
1548 If you get a LaTeX error message, please check whether you have included all
1549 required packages. The packages we use are C<array>, C<booktabs>, C<colortbl>,
1550 C<ctable>, C<graphicx>, C<longtable>, C<lscape>, C<rotating>, C<tabularx>,
1551 C<tabulary>, C<xcolor> and C<xtab>.
1552
1553 C<LaTeX::Table> may throw one of these errors and warnings:
1554
1555 =over
1556
1557 =item C<IO error: Can't ...>
1558
1559 In method generate(), it was not possible to write the LaTeX code to
1560 C<filename>.
1561
1562 =item C<Invalid usage of option ...>
1563
1564 See the examples in this document and in I<examples/examples.pdf> for the
1565 correct usage of this option.
1566
1567 =item C<DEPRECATED. ...>
1568
1569 There were some minor API changes in C<LaTeX::Table> 0.1.0, 0.8.0, 0.9.0,
1570 0.9.3 and 0.9.12. Just apply the changes to the script or contact its author.
1571
1572 B<Important Note:> 0.9.15 will be the last version that includes deprecated
1573 code.
1574
1575 =back
1576
1577 =head1 CONFIGURATION AND ENVIRONMENT
1578
1579 C<LaTeX::Table> requires no configuration files or environment variables.
1580
1581 =head1 DEPENDENCIES
1582
1583 L<Carp>, L<Module::Pluggable>, L<Moose>, L<English>, L<Scalar::Util>,
1584 L<Template>, L<Text::Wrap>
1585
1586 =head1 BUGS AND LIMITATIONS
1587
1588 The width option causes problems with themes using the C<colortbl> package.
1589 You may have to specify here the overhang arguments of the C<\columcolor>
1590 commands manually. Patches are of course welcome.
1591
1592 Please report any bugs or feature requests to
1593 C<bug-latex-table@rt.cpan.org>, or through the web interface at
1594 L<http://rt.cpan.org>.
1595
1596 =head1 SEE ALSO
1597
1598 L<Data::Table>, L<LaTeX::Encode>
1599
1600 =head1 CREDITS
1601
1602 =over
1603
1604 =item David Carlisle for the C<colortbl>, C<longtable>, <ltxtable>,
1605 C<tabularx> and C<tabulary> LaTeX packages.
1606
1607 =item Wybo Dekker for the C<ctable> LaTeX package.
1608
1609 =item Simon Fear for the C<booktabs> LaTeX package. The L<"SYNOPSIS"> table is
1610 the example in his documentation.
1611
1612 =item Andrew Ford (ANDREWF) for many great suggestions. He also wrote
1613 L<LaTeX::Driver> and L<LaTeX::Encode> which are used by I<csv2pdf>.
1614
1615 =item Lapo Filippo Mori for the excellent tutorial I<Tables in LaTeX2e:
1616 Packages and Methods>.
1617
1618 =item Peter Wilson for the C<xtab> LaTeX package.
1619
1620 =back
1621
1622 =head1 AUTHOR
1623
1624 Markus Riester C<< <mriester@gmx.de> >>
1625
1626 =head1 LICENSE AND COPYRIGHT
1627
1628 Copyright (c) 2006-2009, Markus Riester C<< <mriester@gmx.de> >>.
1629
1630 This module is free software; you can redistribute it and/or
1631 modify it under the same terms as Perl itself. See L<perlartistic>.
1632
1633 =head1 DISCLAIMER OF WARRANTY
1634
1635 BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
1636 FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
1637 OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
1638 PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
1639 EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1640 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
1641 ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
1642 YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
1643 NECESSARY SERVICING, REPAIR, OR CORRECTION.
1644
1645 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
1646 WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
1647 REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
1648 LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
1649 OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
1650 THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
1651 RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
1652 FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
1653 SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
1654 SUCH DAMAGES.
1655
1656 =cut
1657
1658 # vim: ft=perl sw=4 ts=4 expandtab
0 use Test::More tests => 11;
1 use Test::NoWarnings;
2
3 BEGIN {
4 use_ok( 'LaTeX::Table' );
5 use_ok( 'LaTeX::Table::Themes::ThemeI' );
6 use_ok( 'LaTeX::Table::Themes::Beamer' );
7 use_ok( 'LaTeX::Table::Themes::Classic' );
8 use_ok( 'LaTeX::Table::Themes::Modern' );
9 use_ok( 'LaTeX::Table::Types::TypeI' );
10 use_ok( 'LaTeX::Table::Types::Ctable' );
11 use_ok( 'LaTeX::Table::Types::Longtable' );
12 use_ok( 'LaTeX::Table::Types::Xtab' );
13 use_ok( 'LaTeX::Table::Types::Std' );
14 }
15
16 diag( "Testing LaTeX::Table $LaTeX::Table::VERSION" );
0 use Test::More tests => 7;
1 use Test::NoWarnings;
2
3 use LaTeX::Table;
4
5 my $test_header = [ ['Name','Beers:2c'], ['','before 4pm', 'after 4pm'] ];
6 my $test_data = [
7 ['Lisa\tmark','0','0'],
8 [ 'Marge','0','1'],
9 [ 'Wiggum','0','5'],
10 [ 'Otto','1','3'],
11 [ 'Homer','2','6'],
12 [ 'Barney','8','16'],
13 ];
14
15 my $table = LaTeX::Table->new({ filename => 'out.tex',
16 label => 'beercounter',
17 maincaption => 'Beer Counter',
18 caption => 'Number of beers before and after 4pm.',
19 header => $test_header,
20 data => $test_data,
21 type => 'ctable',
22 theme => 'Zurich',
23 });
24
25 $table->set_foottable('\tnote{footnotes are placed under the table}');
26
27 my $expected_output =<<'EOT'
28 {
29 \ctable[caption = {Beer Counter. Number of beers before and after 4pm.},
30 cap = {Beer Counter},
31 botcap,
32 label = {beercounter},
33 center,
34 ]{lrr}{\tnote{footnotes are placed under the table}}{
35 \toprule
36 \textbf{Name} & \multicolumn{2}{c}{\textbf{Beers}} \\
37 & \multicolumn{1}{c}{\textbf{before 4pm}} & \multicolumn{1}{c}{\textbf{after 4pm}} \\
38 \midrule
39 Lisa\tmark & 0 & 0 \\
40 Marge & 0 & 1 \\
41 Wiggum & 0 & 5 \\
42 Otto & 1 & 3 \\
43 Homer & 2 & 6 \\
44 Barney & 8 & 16 \\
45 \bottomrule
46 }
47 }
48 EOT
49 ;
50
51 my $output = $table->generate_string();
52 #warn $output;
53 is_deeply([ split("\n",$output) ], [split("\n",$expected_output)], 'without table environment');
54
55
56 $table->set_maincaption(0);
57 $table->set_shortcaption('Beer Counter');
58
59 $expected_output =<<'EOT'
60 {
61 \ctable[caption = {Number of beers before and after 4pm.},
62 cap = {Beer Counter},
63 botcap,
64 label = {beercounter},
65 center,
66 ]{lrr}{\tnote{footnotes are placed under the table}}{
67 \toprule
68 \textbf{Name} & \multicolumn{2}{c}{\textbf{Beers}} \\
69 & \multicolumn{1}{c}{\textbf{before 4pm}} & \multicolumn{1}{c}{\textbf{after 4pm}} \\
70 \midrule
71 Lisa\tmark & 0 & 0 \\
72 Marge & 0 & 1 \\
73 Wiggum & 0 & 5 \\
74 Otto & 1 & 3 \\
75 Homer & 2 & 6 \\
76 Barney & 8 & 16 \\
77 \bottomrule
78 }
79 }
80 EOT
81 ;
82
83 $output = $table->generate_string();
84 #warn $output;
85 is_deeply([ split("\n",$output) ], [split("\n",$expected_output)], 'without table environment');
86
87 $table->set_right(1);
88 $table->set_shortcaption(0);
89 $table->set_caption_top(1);
90
91 $expected_output =<<'EOT'
92 {
93 \ctable[caption = {Number of beers before and after 4pm.},
94 label = {beercounter},
95 right,
96 ]{lrr}{\tnote{footnotes are placed under the table}}{
97 \toprule
98 \textbf{Name} & \multicolumn{2}{c}{\textbf{Beers}} \\
99 & \multicolumn{1}{c}{\textbf{before 4pm}} & \multicolumn{1}{c}{\textbf{after 4pm}} \\
100 \midrule
101 Lisa\tmark & 0 & 0 \\
102 Marge & 0 & 1 \\
103 Wiggum & 0 & 5 \\
104 Otto & 1 & 3 \\
105 Homer & 2 & 6 \\
106 Barney & 8 & 16 \\
107 \bottomrule
108 }
109 }
110 EOT
111 ;
112
113 $output = $table->generate_string();
114 #warn $output;
115 is_deeply([ split("\n",$output) ], [split("\n",$expected_output)], 'without table environment');
116
117 $test_data = [
118 ['Lisa\tmark','0','0'],
119 [ 'Marge','0','1'],
120 [ 'Wiggum','0','5'],
121 [ 'Otto','1','3'],
122 [ 'Homer','This is a looooooooooooooooong longgg linee, my friedn','6'],
123 [ 'Barney','8','16'],
124 ];
125
126 $table->set_data($test_data);
127 $table->set_maxwidth('0.9\textwidth');
128
129 $expected_output =<<'EOT'
130 {
131 \ctable[caption = {Number of beers before and after 4pm.},
132 label = {beercounter},
133 maxwidth = {0.9\textwidth},
134 right,
135 ]{lXr}{\tnote{footnotes are placed under the table}}{
136 \toprule
137 \textbf{Name} & \multicolumn{2}{c}{\textbf{Beers}} \\
138 & \multicolumn{1}{c}{\textbf{before 4pm}} & \multicolumn{1}{c}{\textbf{after 4pm}} \\
139 \midrule
140 Lisa\tmark & 0 & 0 \\
141 Marge & 0 & 1 \\
142 Wiggum & 0 & 5 \\
143 Otto & 1 & 3 \\
144 Homer & This is a looooooooooooooooong longgg linee, my friedn & 6 \\
145 Barney & 8 & 16 \\
146 \bottomrule
147 }
148 }
149 EOT
150 ;
151
152 $output = $table->generate_string();
153 #warn $output;
154 is_deeply([ split("\n",$output) ], [split("\n",$expected_output)],
155 'uses xtabular?');
156
157
158 $table = LaTeX::Table->new(
159 {
160 type => 'ctable',
161 header => [ [ 'Website', 'URL' ] ],
162 data => [
163 [ 'Slashdot', 'http://www.slashdot.org' ],
164 [ 'Perlmonks', ' http://www.perlmonks.org' ],
165 [ 'Google', 'http://www.google.com' ],
166 ],
167 coldef_strategy => {
168 URL => qr{ \A \s* http }xms,
169 URL_COL => '>{\ttfamily}l',
170 },
171 theme => 'Zurich',
172 }
173 );
174
175 $expected_output =<<'EOT'
176 {
177 \ctable[center,
178 ]{l>{\ttfamily}l}{}{
179 \toprule
180 \textbf{Website} & \multicolumn{1}{c}{\textbf{URL}} \\
181 \midrule
182 Slashdot & http://www.slashdot.org \\
183 Perlmonks & http://www.perlmonks.org \\
184 Google & http://www.google.com \\
185 \bottomrule
186 }
187 }
188 EOT
189 ;
190
191 $output = $table->generate_string();
192 is_deeply([ split("\n",$output) ], [split("\n",$expected_output)],
193 'uses _COL_X not specified');
194
195 $table->set_continued(1);
196
197 $expected_output =<<'EOT'
198 {
199 \ctable[center,
200 continued = {(continued)},
201 ]{l>{\ttfamily}l}{}{
202 \toprule
203 \textbf{Website} & \multicolumn{1}{c}{\textbf{URL}} \\
204 \midrule
205 Slashdot & http://www.slashdot.org \\
206 Perlmonks & http://www.perlmonks.org \\
207 Google & http://www.google.com \\
208 \bottomrule
209 }
210 }
211 EOT
212 ;
213
214 $output = $table->generate_string();
215 is_deeply([ split("\n",$output) ], [split("\n",$expected_output)],
216 'continued');
217
0 use Test::More tests => 3;
1 use Test::NoWarnings;
2
3 use strict;
4 use warnings;
5
6 use LaTeX::Table;
7
8
9 my $header = [
10 [ 'Item:2c', '' ],
11 ['\cmidrule(r){1-2}'],
12 [ 'Animal', 'Description', 'Price' ]
13 ];
14
15 my $data = [
16 [ 'Gnat', 'per gram', '13.65' ],
17 [ '', 'each', '0.01' ],
18 [ 'Gnu', 'stuffed', '92.59' ],
19 [ 'Emu', 'stuffed', '33.33' ],
20 [ 'Armadillo', 'frozen', '8.99' ],
21 ];
22
23
24 my $table = LaTeX::Table->new(
25 {
26 filename => 'prices.tex',
27 maincaption => 'Price List',
28 caption => 'Try our special offer today!',
29 label => 'table:prices',
30 position => 'htb',
31 header => $header,
32 data => $data,
33 theme => 'Meyrin',
34 custom_template => '[% DATA_CODE %]',
35 }
36 );
37
38 my $expected_output =<<'EOT'
39 Gnat & per gram & 13.65 \\
40 & each & 0.01 \\
41 Gnu & stuffed & 92.59 \\
42 Emu & stuffed & 33.33 \\
43 Armadillo & frozen & 8.99 \\
44 \bottomrule
45 EOT
46 ;
47
48 my $output = $table->generate_string();
49 is_deeply([ split("\n",$output) ], [split("\n",$expected_output)],
50 'BODY_CODE');
51
52 $table->set_custom_template('[% HEADER_CODE %]');
53
54 $expected_output =<<'EOT'
55 \toprule
56 \multicolumn{2}{c}{Item} & \\
57 \cmidrule(r){1-2}
58 Animal & Description & Price \\
59 \midrule
60 EOT
61 ;
62
63 $output = $table->generate_string();
64 is_deeply([ split("\n",$output) ], [split("\n",$expected_output)],
65 'HEADER_CODE');
0 use Test::More tests => 21;
1 use Test::NoWarnings;
2
3 use LaTeX::Table;
4
5 my $test_header
6 = [ [ 'Name', 'Beers:2c' ], [ '', 'before 4pm', 'after 4pm' ] ];
7 my $test_data = [
8 [ 'Lisa', '0', '0' ],
9 [ 'Marge', '0', '1' ],
10 [ 'Wiggum', '0', '5' ],
11 [ 'Otto', '1', '3' ],
12 [ 'Homer', '2', '6' ],
13 [ 'Barney', '8', '16' ],
14 ];
15
16 my $table = LaTeX::Table->new(
17 { filename => 't/tmp/out.tex',
18 label => 'beercounter',
19 maincaption => 'Beer Counter',
20 caption => 'Number of beers before and after 4pm.',
21 environment => 0,
22 theme => 'Dresden',
23 header => $test_header,
24 data => $test_data,
25 }
26 );
27
28 my $expected_output = <<'EOT'
29 \begin{tabular}{|l||r|r|}
30 \hline
31 \multicolumn{1}{|c||}{\textbf{Name}} & \multicolumn{2}{c|}{\textbf{Beers}} \\
32 \multicolumn{1}{|c||}{\textbf{}} & \multicolumn{1}{c|}{\textbf{before 4pm}} & \multicolumn{1}{c|}{\textbf{after 4pm}} \\
33 \hline
34 \hline
35 Lisa & 0 & 0 \\
36 Marge & 0 & 1 \\
37 Wiggum & 0 & 5 \\
38 Otto & 1 & 3 \\
39 Homer & 2 & 6 \\
40 Barney & 8 & 16 \\
41 \hline
42 \end{tabular}
43 EOT
44 ;
45
46 my $output = $table->generate_string();
47 my @expected_output = split "\n", $expected_output;
48
49 is_deeply(
50 [ split( "\n", $output ) ],
51 \@expected_output,
52 'without table environment'
53 );
54
55 mkdir 't/tmp';
56 $table->generate();
57
58 open my $FH, '<', 't/tmp/out.tex';
59 my @filecontent = <$FH>;
60 chomp @filecontent;
61 close $FH;
62
63 is_deeply( \@filecontent, [@expected_output],
64 'without table environment, generate()' )
65 or die;
66
67 unlink 't/tmp/out.tex';
68 rmdir 't/tmp';
69 ## with table environment
70 $table->set_environment(1);
71
72 $expected_output = <<'EOT'
73 \begin{table}
74 \centering
75 \begin{tabular}{|l||r|r|}
76 \hline
77 \multicolumn{1}{|c||}{\textbf{Name}} & \multicolumn{2}{c|}{\textbf{Beers}} \\
78 \multicolumn{1}{|c||}{\textbf{}} & \multicolumn{1}{c|}{\textbf{before 4pm}} & \multicolumn{1}{c|}{\textbf{after 4pm}} \\
79 \hline
80 \hline
81 Lisa & 0 & 0 \\
82 Marge & 0 & 1 \\
83 Wiggum & 0 & 5 \\
84 Otto & 1 & 3 \\
85 Homer & 2 & 6 \\
86 Barney & 8 & 16 \\
87 \hline
88 \end{tabular}
89 \caption[Beer Counter]{\textbf{Beer Counter. }Number of beers before and after 4pm.}
90 \label{beercounter}
91 \end{table}
92 EOT
93 ;
94 $output = $table->generate_string();
95 is_deeply(
96 [ split( "\n", $output ) ],
97 [ split( "\n", $expected_output ) ],
98 'with table environment'
99 );
100
101 $table->set_continued(1);
102 $expected_output = <<'EOT'
103 \addtocounter{table}{-1}\begin{table}
104 \centering
105 \begin{tabular}{|l||r|r|}
106 \hline
107 \multicolumn{1}{|c||}{\textbf{Name}} & \multicolumn{2}{c|}{\textbf{Beers}} \\
108 \multicolumn{1}{|c||}{\textbf{}} & \multicolumn{1}{c|}{\textbf{before 4pm}} & \multicolumn{1}{c|}{\textbf{after 4pm}} \\
109 \hline
110 \hline
111 Lisa & 0 & 0 \\
112 Marge & 0 & 1 \\
113 Wiggum & 0 & 5 \\
114 Otto & 1 & 3 \\
115 Homer & 2 & 6 \\
116 Barney & 8 & 16 \\
117 \hline
118 \end{tabular}
119 \caption[Beer Counter]{\textbf{Beer Counter. }Number of beers before and after 4pm. (continued)}
120 \label{beercounter}
121 \end{table}
122 EOT
123 ;
124 $output = $table->generate_string();
125 is_deeply(
126 [ split( "\n", $output ) ],
127 [ split( "\n", $expected_output ) ],
128 'with table environment'
129 );
130
131 $table->set_continued(0);
132 # without label and maincaption
133 $table->set_environment(1);
134 $table->set_label('');
135 $table->set_maincaption('');
136
137 $expected_output = <<'EOT'
138 \begin{table}
139 \centering
140 \begin{tabular}{|l||r|r|}
141 \hline
142 \multicolumn{1}{|c||}{\textbf{Name}} & \multicolumn{2}{c|}{\textbf{Beers}} \\
143 \multicolumn{1}{|c||}{\textbf{}} & \multicolumn{1}{c|}{\textbf{before 4pm}} & \multicolumn{1}{c|}{\textbf{after 4pm}} \\
144 \hline
145 \hline
146 Lisa & 0 & 0 \\
147 Marge & 0 & 1 \\
148 Wiggum & 0 & 5 \\
149 Otto & 1 & 3 \\
150 Homer & 2 & 6 \\
151 Barney & 8 & 16 \\
152 \hline
153 \end{tabular}
154 \caption{Number of beers before and after 4pm.}
155 \end{table}
156 EOT
157 ;
158
159 $output = $table->generate_string();
160 is_deeply(
161 [ split( "\n", $output ) ],
162 [ split( "\n", $expected_output ) ],
163 'with table environment, without maincaption and label'
164 );
165
166 ## without center
167
168 $table = LaTeX::Table->new(
169 { environment => 1,
170 center => 0,
171 theme => 'Dresden',
172 header => $test_header,
173 data => $test_data,
174 }
175 );
176 $expected_output = <<'EOT'
177 \begin{table}
178 \begin{tabular}{|l||r|r|}
179 \hline
180 \multicolumn{1}{|c||}{\textbf{Name}} & \multicolumn{2}{c|}{\textbf{Beers}} \\
181 \multicolumn{1}{|c||}{\textbf{}} & \multicolumn{1}{c|}{\textbf{before 4pm}} & \multicolumn{1}{c|}{\textbf{after 4pm}} \\
182 \hline
183 \hline
184 Lisa & 0 & 0 \\
185 Marge & 0 & 1 \\
186 Wiggum & 0 & 5 \\
187 Otto & 1 & 3 \\
188 Homer & 2 & 6 \\
189 Barney & 8 & 16 \\
190 \hline
191 \end{tabular}
192 \end{table}
193 EOT
194 ;
195
196 $output = $table->generate_string();
197 is_deeply(
198 [ split( "\n", $output ) ],
199 [ split( "\n", $expected_output ) ],
200 'with table environment, without maincaption, center and label'
201 );
202
203 $table = LaTeX::Table->new(
204 { environment => 1,
205 center => 0,
206 caption_top => 1,
207 caption => 'test caption',
208 header => $test_header,
209 data => $test_data,
210 theme => 'Zurich',
211 }
212 );
213
214 $output = $table->generate_string();
215
216 $expected_output = <<'EOT'
217 \begin{table}
218 \caption{test caption}
219 \begin{tabular}{lrr}
220 \toprule
221 \textbf{Name} & \multicolumn{2}{c}{\textbf{Beers}} \\
222 & \multicolumn{1}{c}{\textbf{before 4pm}} & \multicolumn{1}{c}{\textbf{after 4pm}} \\
223 \midrule
224 Lisa & 0 & 0 \\
225 Marge & 0 & 1 \\
226 Wiggum & 0 & 5 \\
227 Otto & 1 & 3 \\
228 Homer & 2 & 6 \\
229 Barney & 8 & 16 \\
230 \bottomrule
231 \end{tabular}
232 \end{table}
233 EOT
234 ;
235
236 is_deeply(
237 [ split( "\n", $output ) ],
238 [ split( "\n", $expected_output ) ],
239 'with table environment, without maincaption, center and label'
240 );
241
242 $table->set_caption_top('topcaption');
243 $output = $table->generate_string();
244
245 $expected_output = <<'EOT'
246 \begin{table}
247 \topcaption{test caption}
248 \begin{tabular}{lrr}
249 \toprule
250 \textbf{Name} & \multicolumn{2}{c}{\textbf{Beers}} \\
251 & \multicolumn{1}{c}{\textbf{before 4pm}} & \multicolumn{1}{c}{\textbf{after 4pm}} \\
252 \midrule
253 Lisa & 0 & 0 \\
254 Marge & 0 & 1 \\
255 Wiggum & 0 & 5 \\
256 Otto & 1 & 3 \\
257 Homer & 2 & 6 \\
258 Barney & 8 & 16 \\
259 \bottomrule
260 \end{tabular}
261 \end{table}
262 EOT
263 ;
264
265 is_deeply(
266 [ split( "\n", $output ) ],
267 [ split( "\n", $expected_output ) ],
268 'with table environment, without maincaption, center and label'
269 );
270
271 ## with coldef
272 $table = LaTeX::Table->new(
273 { environment => 0,
274 coldef => "|l||l|l|",
275 header => $test_header,
276 data => $test_data,
277 theme => 'Dresden',
278 }
279 );
280 $expected_output = <<'EOT'
281 \begin{tabular}{|l||l|l|}
282 \hline
283 \multicolumn{1}{|c||}{\textbf{Name}} & \multicolumn{2}{c|}{\textbf{Beers}} \\
284 \multicolumn{1}{|c||}{\textbf{}} & \multicolumn{1}{c|}{\textbf{before 4pm}} & \multicolumn{1}{c|}{\textbf{after 4pm}} \\
285 \hline
286 \hline
287 Lisa & 0 & 0 \\
288 Marge & 0 & 1 \\
289 Wiggum & 0 & 5 \\
290 Otto & 1 & 3 \\
291 Homer & 2 & 6 \\
292 Barney & 8 & 16 \\
293 \hline
294 \end{tabular}
295 EOT
296 ;
297
298 $output = $table->generate_string();
299 is_deeply(
300 [ split( "\n", $output ) ],
301 [ split( "\n", $expected_output ) ],
302 'with coldef'
303 );
304
305 $test_data = [
306 [ 'Lisa', '0', '0' ],
307 [ 'Marge', '0', '1' ],
308 [ 'Wiggum', '0', '' ],
309 [ 'Otto', ' ', '' ],
310 [ 'Homer', '2', '6' ],
311 [ 'Barney', '8', '16' ],
312 ];
313
314 $table = LaTeX::Table->new(
315 { environment => 0,
316 header => $test_header,
317 data => $test_data,
318 }
319 );
320
321 $expected_output = <<'EOT'
322 \begin{tabular}{lrr}
323 \toprule
324 Name & \multicolumn{2}{c}{Beers} \\
325 & before 4pm & after 4pm \\
326 \midrule
327 Lisa & 0 & 0 \\
328 Marge & 0 & 1 \\
329 Wiggum & 0 & \\
330 Otto & & \\
331 Homer & 2 & 6 \\
332 Barney & 8 & 16 \\
333 \bottomrule
334 \end{tabular}
335 EOT
336 ;
337
338 $output = $table->generate_string();
339 is_deeply(
340 [ split( "\n", $output ) ],
341 [ split( "\n", $expected_output ) ],
342 'missing values'
343 ) || diag $output;
344
345 my $header = [ [ 'Character', 'Fullname', 'Voice' ], ];
346 my $data = [
347 [ 'Homer', 'Homer Jay Simpson', 'Dan Castellaneta', ],
348 [],
349 [ 'Marge', 'Marjorie Simpson (nee Bouvier)', 'Julie Kavner', ],
350 [ 'Bart', 'Bartholomew Jojo Simpson', 'Nancy Cartwright', ],
351 [ 'Lisa', 'Elizabeth Marie Simpson', 'Yeardley Smith', ],
352 [ 'Maggie',
353 'Margaret Simpson',
354 'Elizabeth Taylor, Nancy Cartwright, James Earl Jones,'
355 . 'Yeardley Smith, Harry Shearer',
356 ],
357 ];
358
359 #no header test
360 $table = LaTeX::Table->new(
361 { data => $data,
362 width => '0.9\textwidth',
363 width_environment => 'tabularx',
364 position => 'ht',
365 theme => 'Zurich',
366 }
367 );
368 $expected_output = <<'EOT'
369 \begin{table}[ht]
370 \centering
371 \begin{tabularx}{0.9\textwidth}{lXX}
372 \toprule
373 Homer & Homer Jay Simpson & Dan Castellaneta \\
374 \midrule
375 Marge & Marjorie Simpson (nee Bouvier) & Julie Kavner \\
376 Bart & Bartholomew Jojo Simpson & Nancy Cartwright \\
377 Lisa & Elizabeth Marie Simpson & Yeardley Smith \\
378 Maggie & Margaret Simpson & Elizabeth Taylor, Nancy Cartwright, James Earl Jones,Yeardley Smith, Harry Shearer \\
379 \bottomrule
380 \end{tabularx}
381 \end{table}
382 EOT
383 ;
384
385 $output = $table->generate_string();
386 is_deeply(
387 [ split( "\n", $output ) ],
388 [ split( "\n", $expected_output ) ],
389 'no header'
390 );
391
392 $table->set_width_environment('tabulary');
393 $expected_output = <<'EOT'
394 \begin{table}[ht]
395 \centering
396 \begin{tabulary}{0.9\textwidth}{lLL}
397 \toprule
398 Homer & Homer Jay Simpson & Dan Castellaneta \\
399 \midrule
400 Marge & Marjorie Simpson (nee Bouvier) & Julie Kavner \\
401 Bart & Bartholomew Jojo Simpson & Nancy Cartwright \\
402 Lisa & Elizabeth Marie Simpson & Yeardley Smith \\
403 Maggie & Margaret Simpson & Elizabeth Taylor, Nancy Cartwright, James Earl Jones,Yeardley Smith, Harry Shearer \\
404 \bottomrule
405 \end{tabulary}
406 \end{table}
407 EOT
408 ;
409
410 $output = $table->generate_string();
411 is_deeply(
412 [ split( "\n", $output ) ],
413 [ split( "\n", $expected_output ) ],
414 'tabulary'
415 );
416
417
418 ## tabularx test
419 $table = LaTeX::Table->new(
420 { header => $header,
421 data => $data,
422 width => '0.9\textwidth',
423 width_environment => 'tabularx',
424 position => 'ht',
425 theme => 'Zurich',
426 }
427 );
428
429 $expected_output = <<'EOT'
430 \begin{table}[ht]
431 \centering
432 \begin{tabularx}{0.9\textwidth}{lXX}
433 \toprule
434 \textbf{Character} & \multicolumn{1}{c}{\textbf{Fullname}} & \multicolumn{1}{c}{\textbf{Voice}} \\
435 \midrule
436 Homer & Homer Jay Simpson & Dan Castellaneta \\
437 \midrule
438 Marge & Marjorie Simpson (nee Bouvier) & Julie Kavner \\
439 Bart & Bartholomew Jojo Simpson & Nancy Cartwright \\
440 Lisa & Elizabeth Marie Simpson & Yeardley Smith \\
441 Maggie & Margaret Simpson & Elizabeth Taylor, Nancy Cartwright, James Earl Jones,Yeardley Smith, Harry Shearer \\
442 \bottomrule
443 \end{tabularx}
444 \end{table}
445 EOT
446 ;
447
448 $output = $table->generate_string();
449 is_deeply(
450 [ split( "\n", $output ) ],
451 [ split( "\n", $expected_output ) ],
452 'with coldef'
453 );
454
455 $table->set_width_environment('tabular*');
456
457 $expected_output = <<'EOT'
458 \begin{table}[ht]
459 \centering
460 \begin{tabular*}{0.9\textwidth}{l@{\extracolsep{\fill}}p{5cm}p{5cm}}
461 \toprule
462 \textbf{Character} & \multicolumn{1}{c}{\textbf{Fullname}} & \multicolumn{1}{c}{\textbf{Voice}} \\
463 \midrule
464 Homer & Homer Jay Simpson & Dan Castellaneta \\
465 \midrule
466 Marge & Marjorie Simpson (nee Bouvier) & Julie Kavner \\
467 Bart & Bartholomew Jojo Simpson & Nancy Cartwright \\
468 Lisa & Elizabeth Marie Simpson & Yeardley Smith \\
469 Maggie & Margaret Simpson & Elizabeth Taylor, Nancy Cartwright, James Earl Jones,Yeardley Smith, Harry Shearer \\
470 \bottomrule
471 \end{tabular*}
472 \end{table}
473 EOT
474 ;
475
476 $output = $table->generate_string();
477 is_deeply(
478 [ split( "\n", $output ) ],
479 [ split( "\n", $expected_output ) ],
480 'with coldef'
481 );
482
483 $test_header = [ [ 'A:3c' ] , [ 'A:2c', 'B' ], ['A', 'B', 'C' ], ];
484 $test_data = [ [ '1', 'w', 'x' ], [ '2', 'c:2c' ], ];
485
486 $table = LaTeX::Table->new(
487 { environment => 0,
488 header => $test_header,
489 data => $test_data,
490 theme => 'Dresden',
491 }
492 );
493
494 $output = $table->generate_string();
495
496 $expected_output = <<'EOT'
497 \begin{tabular}{|r||l|l|}
498 \hline
499 \multicolumn{3}{|c|}{\textbf{A}} \\
500 \multicolumn{2}{|c|}{\textbf{A}} & \multicolumn{1}{c|}{\textbf{B}} \\
501 \multicolumn{1}{|c||}{\textbf{A}} & \multicolumn{1}{c|}{\textbf{B}} & \multicolumn{1}{c|}{\textbf{C}} \\
502 \hline
503 \hline
504 1 & w & x \\
505 2 & \multicolumn{2}{c|}{c} \\
506 \hline
507 \end{tabular}
508 EOT
509 ;
510
511
512 $output = $table->generate_string();
513 is_deeply(
514 [ split( "\n", $output ) ],
515 [ split( "\n", $expected_output ) ],
516 'with very complicated multicolum shortcuts'
517 );
518
519 $table->set_theme('NYC');
520
521 $expected_output = <<'EOT'
522 \definecolor{latextbl}{RGB}{78,130,190}
523 \setlength{\extrarowheight}{1pt}
524 \begin{tabular}{|rll|}
525 \hline
526 \rowcolor{latextbl}\multicolumn{3}{|>{\columncolor{latextbl}}c|}{\color{white}\textbf{A}} \\
527 \rowcolor{latextbl}\multicolumn{2}{|>{\columncolor{latextbl}}c}{\color{white}\textbf{A}} & \multicolumn{1}{>{\columncolor{latextbl}}c|}{\color{white}\textbf{B}} \\
528 \rowcolor{latextbl}\multicolumn{1}{|>{\columncolor{latextbl}}c}{\color{white}\textbf{A}} & \multicolumn{1}{>{\columncolor{latextbl}}c}{\color{white}\textbf{B}} & \multicolumn{1}{>{\columncolor{latextbl}}c|}{\color{white}\textbf{C}} \\
529 \hline
530 \rowcolor{latextbl!25}1 & w & x \\
531 \rowcolor{latextbl!10}2 & \multicolumn{2}{>{\columncolor{latextbl!10}}c|}{c} \\
532 \hline
533 \end{tabular}
534 EOT
535 ;
536
537 $output = $table->generate_string();
538 is_deeply(
539 [ split( "\n", $output ) ],
540 [ split( "\n", $expected_output ) ],
541 'theme with colordef'
542 );
543
544 $table->set_resizebox(['0.6\textwidth']);
545
546
547 $expected_output = <<'EOT'
548 \definecolor{latextbl}{RGB}{78,130,190}
549 \setlength{\extrarowheight}{1pt}
550 \resizebox{0.6\textwidth}{!}{
551 \begin{tabular}{|rll|}
552 \hline
553 \rowcolor{latextbl}\multicolumn{3}{|>{\columncolor{latextbl}}c|}{\color{white}\textbf{A}} \\
554 \rowcolor{latextbl}\multicolumn{2}{|>{\columncolor{latextbl}}c}{\color{white}\textbf{A}} & \multicolumn{1}{>{\columncolor{latextbl}}c|}{\color{white}\textbf{B}} \\
555 \rowcolor{latextbl}\multicolumn{1}{|>{\columncolor{latextbl}}c}{\color{white}\textbf{A}} & \multicolumn{1}{>{\columncolor{latextbl}}c}{\color{white}\textbf{B}} & \multicolumn{1}{>{\columncolor{latextbl}}c|}{\color{white}\textbf{C}} \\
556 \hline
557 \rowcolor{latextbl!25}1 & w & x \\
558 \rowcolor{latextbl!10}2 & \multicolumn{2}{>{\columncolor{latextbl!10}}c|}{c} \\
559 \hline
560 \end{tabular}}
561 EOT
562 ;
563
564 $output = $table->generate_string();
565 is_deeply(
566 [ split( "\n", $output ) ],
567 [ split( "\n", $expected_output ) ],
568 'theme with colordef and resizebox'
569 );
570
571 $table->set_resizebox(['300pt', '200pt']);
572 $expected_output = <<'EOT'
573 \definecolor{latextbl}{RGB}{78,130,190}
574 \setlength{\extrarowheight}{1pt}
575 \resizebox{300pt}{200pt}{
576 \begin{tabular}{|rll|}
577 \hline
578 \rowcolor{latextbl}\multicolumn{3}{|>{\columncolor{latextbl}}c|}{\color{white}\textbf{A}} \\
579 \rowcolor{latextbl}\multicolumn{2}{|>{\columncolor{latextbl}}c}{\color{white}\textbf{A}} & \multicolumn{1}{>{\columncolor{latextbl}}c|}{\color{white}\textbf{B}} \\
580 \rowcolor{latextbl}\multicolumn{1}{|>{\columncolor{latextbl}}c}{\color{white}\textbf{A}} & \multicolumn{1}{>{\columncolor{latextbl}}c}{\color{white}\textbf{B}} & \multicolumn{1}{>{\columncolor{latextbl}}c|}{\color{white}\textbf{C}} \\
581 \hline
582 \rowcolor{latextbl!25}1 & w & x \\
583 \rowcolor{latextbl!10}2 & \multicolumn{2}{>{\columncolor{latextbl!10}}c|}{c} \\
584 \hline
585 \end{tabular}}
586 EOT
587 ;
588
589 $output = $table->generate_string();
590 is_deeply(
591 [ split( "\n", $output ) ],
592 [ split( "\n", $expected_output ) ],
593 'theme with colordef and resizebox'
594 );
595
596 $test_data = [ [ '1', 'w', 'x' ],['\hline' ], [ '2', 'c:2c' ], ];
597
598 $table = LaTeX::Table->new(
599 {
600 data => $test_data,
601 theme => 'NYC',
602 columns_like_header => [ 0 ],
603 }
604 );
605
606 $expected_output = <<'EOT'
607 \definecolor{latextbl}{RGB}{78,130,190}
608 \begin{table}
609 \centering
610 \setlength{\extrarowheight}{1pt}
611 \begin{tabular}{|rll|}
612 \hline
613 \rowcolor{latextbl!25}\multicolumn{1}{|>{\columncolor{latextbl}}r}{\color{white}\textbf{1}} & w & x \\
614 \hline
615 \rowcolor{latextbl!10}\multicolumn{1}{|>{\columncolor{latextbl}}r}{\color{white}\textbf{2}} & \multicolumn{2}{>{\columncolor{latextbl!10}}c|}{c} \\
616 \hline
617 \end{tabular}
618 \end{table}
619 EOT
620 ;
621
622
623 $output = $table->generate_string();
624
625 is_deeply(
626 [ split( "\n", $output ) ],
627 [ split( "\n", $expected_output ) ],
628 'theme with colordef and resizebox'
629 ) || diag $output;
630
631 $header = [ ['Time', 'Weekdays:5c'], [], [ '', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday' ] ];
632
633 $data = [
634 [ '9.00', '','', '', '', '', ],
635 [ '12.00', '','', '', '', '', ],
636 ];
637
638 $table = LaTeX::Table->new(
639 {
640 header => $header,
641 data => $data,
642 header_sideways => 1,
643 sideways => 1,
644 theme => 'NYC',
645 }
646 );
647
648 $expected_output = <<'EOT'
649 \definecolor{latextbl}{RGB}{78,130,190}
650 \begin{sidewaystable}
651 \centering
652 \setlength{\extrarowheight}{1pt}
653 \begin{tabular}{|rlllll|}
654 \hline
655 \rowcolor{latextbl}\multicolumn{1}{|>{\columncolor{latextbl}}c}{\color{white}\textbf{\begin{sideways}Time\end{sideways}}} & \multicolumn{5}{>{\columncolor{latextbl}}c|}{\color{white}\textbf{\begin{sideways}Weekdays\end{sideways}}} \\
656 \hline
657 \rowcolor{latextbl}\multicolumn{1}{|>{\columncolor{latextbl}}c}{\color{white}\textbf{\begin{sideways}\end{sideways}}} & \multicolumn{1}{>{\columncolor{latextbl}}c}{\color{white}\textbf{\begin{sideways}Monday\end{sideways}}} & \multicolumn{1}{>{\columncolor{latextbl}}c}{\color{white}\textbf{\begin{sideways}Tuesday\end{sideways}}} & \multicolumn{1}{>{\columncolor{latextbl}}c}{\color{white}\textbf{\begin{sideways}Wednesday\end{sideways}}} & \multicolumn{1}{>{\columncolor{latextbl}}c}{\color{white}\textbf{\begin{sideways}Thursday\end{sideways}}} & \multicolumn{1}{>{\columncolor{latextbl}}c|}{\color{white}\textbf{\begin{sideways}Friday\end{sideways}}} \\
658 \hline
659 \rowcolor{latextbl!25}9.00 & & & & & \\
660 \rowcolor{latextbl!10}12.00 & & & & & \\
661 \hline
662 \end{tabular}
663 \end{sidewaystable}
664 EOT
665 ;
666
667
668 $output = $table->generate_string();
669
670 is_deeply(
671 [ split( "\n", $output ) ],
672 [ split( "\n", $expected_output ) ],
673 'NYC header sideways'
674 ) || diag $output;
675
676
0 use Test::More tests => 6;
1 use Test::NoWarnings;
2
3 use LaTeX::Table;
4
5 my $test_header = [ ['Name','Beers:2c'], ['','before 4pm', 'after 4pm'] ];
6 my $test_data = [
7 ['Lisa','0','0'],
8 [ 'Marge','0','1'],
9 [ 'Wiggum','0','5'],
10 [ 'Otto','1','3'],
11 [ 'Homer','2','6'],
12 [ 'Barney','8','16'],
13 ];
14
15 my $table = LaTeX::Table->new({ filename => 'out.tex',
16 label => 'beercounter',
17 maincaption => 'Beer Counter',
18 caption => 'Number of beers before and after 4pm.',
19 header => $test_header,
20 data => $test_data,
21 type => 'xtab',
22 theme => 'Dresden',
23 });
24
25 my $expected_output =<<'EOT'
26 {
27 \bottomcaption[Beer Counter]{\textbf{Beer Counter. }Number of beers before and after 4pm.}
28 \label{beercounter}
29
30 \tablehead{\hline
31 \multicolumn{1}{|c||}{\textbf{Name}} & \multicolumn{2}{c|}{\textbf{Beers}} \\
32 \multicolumn{1}{|c||}{\textbf{}} & \multicolumn{1}{c|}{\textbf{before 4pm}} & \multicolumn{1}{c|}{\textbf{after 4pm}} \\
33 \hline
34 \hline
35 }
36 \tabletail{\hline
37 \hline
38 \multicolumn{3}{|r|}{{Continued on next page}} \\
39 \hline
40 }
41 \tablelasttail{}
42 \begin{center}
43 \begin{xtabular}{|l||r|r|}
44 Lisa & 0 & 0 \\
45 Marge & 0 & 1 \\
46 Wiggum & 0 & 5 \\
47 Otto & 1 & 3 \\
48 Homer & 2 & 6 \\
49 Barney & 8 & 16 \\
50 \hline
51 \end{xtabular}
52 \end{center}
53 }
54 EOT
55 ;
56
57 my $output = $table->generate_string();
58 #warn $output;
59 is_deeply([ split("\n",$output) ], [split("\n",$expected_output)], 'without table environment');
60
61 $table->set_tabletail(q{ });
62
63 $expected_output =<<'EOT'
64 {
65 \bottomcaption[Beer Counter]{\textbf{Beer Counter. }Number of beers before and after 4pm.}
66 \label{beercounter}
67
68 \tablehead{\hline
69 \multicolumn{1}{|c||}{\textbf{Name}} & \multicolumn{2}{c|}{\textbf{Beers}} \\
70 \multicolumn{1}{|c||}{\textbf{}} & \multicolumn{1}{c|}{\textbf{before 4pm}} & \multicolumn{1}{c|}{\textbf{after 4pm}} \\
71 \hline
72 \hline
73 }
74 \tabletail{ \hline
75 }
76 \tablelasttail{}
77 \begin{center}
78 \begin{xtabular}{|l||r|r|}
79 Lisa & 0 & 0 \\
80 Marge & 0 & 1 \\
81 Wiggum & 0 & 5 \\
82 Otto & 1 & 3 \\
83 Homer & 2 & 6 \\
84 Barney & 8 & 16 \\
85 \hline
86 \end{xtabular}
87 \end{center}
88 }
89 EOT
90 ;
91
92 $output = $table->generate_string();
93
94 is_deeply([ split("\n",$output) ], [split("\n",$expected_output)],
95 'without table environment, custom tabletail') || diag $output;
96
97 $table->set_caption_top(1);
98 $table->set_center(0);
99
100 $expected_output =<<'EOT'
101 {
102 \topcaption[Beer Counter]{\textbf{Beer Counter. }Number of beers before and after 4pm.}
103 \label{beercounter}
104
105 \tablefirsthead{\hline
106 \multicolumn{1}{|c||}{\textbf{Name}} & \multicolumn{2}{c|}{\textbf{Beers}} \\
107 \multicolumn{1}{|c||}{\textbf{}} & \multicolumn{1}{c|}{\textbf{before 4pm}} & \multicolumn{1}{c|}{\textbf{after 4pm}} \\
108 \hline
109 \hline
110 }
111 \tablehead{\multicolumn{3}{c}{{ \normalsize \tablename\ \thetable: Continued from previous page}}\\[\abovecaptionskip]
112 \hline
113 \multicolumn{1}{|c||}{\textbf{Name}} & \multicolumn{2}{c|}{\textbf{Beers}} \\
114 \multicolumn{1}{|c||}{\textbf{}} & \multicolumn{1}{c|}{\textbf{before 4pm}} & \multicolumn{1}{c|}{\textbf{after 4pm}} \\
115 \hline
116 \hline
117 }
118
119 \tabletail{ \hline
120 }
121 \tablelasttail{}
122 \begin{xtabular}{|l||r|r|}
123 Lisa & 0 & 0 \\
124 Marge & 0 & 1 \\
125 Wiggum & 0 & 5 \\
126 Otto & 1 & 3 \\
127 Homer & 2 & 6 \\
128 Barney & 8 & 16 \\
129 \hline
130 \end{xtabular}
131
132 }
133 EOT
134 ;
135
136 $output = $table->generate_string();
137
138 is_deeply([ split("\n",$output) ], [split("\n",$expected_output)],
139 'without table environment, topcaption custom tabletail');
140
141 $table->set_caption_top('topcaption');
142
143 $expected_output =<<'EOT'
144 {
145 \topcaption[Beer Counter]{\textbf{Beer Counter. }Number of beers before and after 4pm.}
146 \label{beercounter}
147
148 \tablefirsthead{\hline
149 \multicolumn{1}{|c||}{\textbf{Name}} & \multicolumn{2}{c|}{\textbf{Beers}} \\
150 \multicolumn{1}{|c||}{\textbf{}} & \multicolumn{1}{c|}{\textbf{before 4pm}} & \multicolumn{1}{c|}{\textbf{after 4pm}} \\
151 \hline
152 \hline
153 }
154 \tablehead{\multicolumn{3}{c}{{ \normalsize \tablename\ \thetable: Continued from previous page}}\\[\abovecaptionskip]
155 \hline
156 \multicolumn{1}{|c||}{\textbf{Name}} & \multicolumn{2}{c|}{\textbf{Beers}} \\
157 \multicolumn{1}{|c||}{\textbf{}} & \multicolumn{1}{c|}{\textbf{before 4pm}} & \multicolumn{1}{c|}{\textbf{after 4pm}} \\
158 \hline
159 \hline
160 }
161
162 \tabletail{ \hline
163 }
164 \tablelasttail{}
165 \begin{xtabular}{|l||r|r|}
166 Lisa & 0 & 0 \\
167 Marge & 0 & 1 \\
168 Wiggum & 0 & 5 \\
169 Otto & 1 & 3 \\
170 Homer & 2 & 6 \\
171 Barney & 8 & 16 \\
172 \hline
173 \end{xtabular}
174
175 }
176 EOT
177 ;
178
179 $output = $table->generate_string();
180
181 is_deeply([ split("\n",$output) ], [split("\n",$expected_output)],
182 'without table environment, topcaption custom tabletail');
183
184
185 $table->set_tableheadmsg(0);
186 $table->set_custom_tabular_environment('mpxtabular');
187
188 $expected_output =<<'EOT'
189 {
190 \topcaption[Beer Counter]{\textbf{Beer Counter. }Number of beers before and after 4pm.}
191 \label{beercounter}
192
193 \tablehead{\hline
194 \multicolumn{1}{|c||}{\textbf{Name}} & \multicolumn{2}{c|}{\textbf{Beers}} \\
195 \multicolumn{1}{|c||}{\textbf{}} & \multicolumn{1}{c|}{\textbf{before 4pm}} & \multicolumn{1}{c|}{\textbf{after 4pm}} \\
196 \hline
197 \hline
198 }
199 \tabletail{ \hline
200 }
201 \tablelasttail{}
202 \begin{mpxtabular}{|l||r|r|}
203 Lisa & 0 & 0 \\
204 Marge & 0 & 1 \\
205 Wiggum & 0 & 5 \\
206 Otto & 1 & 3 \\
207 Homer & 2 & 6 \\
208 Barney & 8 & 16 \\
209 \hline
210 \end{mpxtabular}
211
212 }
213 EOT
214 ;
215
216 $output = $table->generate_string();
217
218 is_deeply([ split("\n",$output) ], [split("\n",$expected_output)],
219 'without table environment, topcaption custom tabletail');
220
0 use Test::More tests => 9;
1 use Test::NoWarnings;
2
3 use LaTeX::Table;
4
5 my $table = LaTeX::Table->new({ filename => 'out.tex',
6 label => 'beercounter',
7 maincaption => 'Beer Counter',
8 caption => 'Number of beers before and after 4pm.',
9 theme => 'Zurich',
10 });
11
12 my $test_def = 'test:1c';
13
14 is($table->_add_mc_def({ value => $test_def, align => 'r', cols => 2}), $test_def, 'no adding if already has a def');
15 is($table->_add_mc_def({ value => 'test', align => 'r', cols => 2}), 'test:2r', 'no adding if already has a def');
16 is_deeply($table->_get_mc_def('test'), { value => 'test' }, 'get without def');
17 is_deeply($table->_get_mc_def('test:2c'), { value => 'test', align => 'c', cols => 2 }, 'get with def');
18
19 is_deeply($table->_add_font_family('test:2r', 'bf'), '\\textbf{test}:2r', 'add bold fonts');
20 is($table->_extract_number_columns('test:2c'), 2, 'columwidth correct');
21 is($table->_extract_number_columns('test:2'), 1, 'columwidth correct');
22
23
24 my $header = [ [ 'A:3c'], ['A:2c', 'B'], ['A', 'B', 'C'], ];
25 my $data = [ [ 'D:3c'], ['D:2c', '1.2'], ['D', 'E', '1.3'], ];
26
27 $table = LaTeX::Table->new(
28 { header => $header,
29 data => $data,
30 theme => 'Zurich',
31 }
32 );
33
34 $expected_output = <<'EOT'
35 \begin{table}
36 \centering
37 \begin{tabular}{llr}
38 \toprule
39 \multicolumn{3}{c}{\textbf{A}} \\
40 \multicolumn{2}{c}{\textbf{A}} & \multicolumn{1}{c}{\textbf{B}} \\
41 \textbf{A} & \multicolumn{1}{c}{\textbf{B}} & \multicolumn{1}{c}{\textbf{C}} \\
42 \midrule
43 \multicolumn{3}{c}{D} \\
44 \multicolumn{2}{c}{D} & 1.2 \\
45 D & E & 1.3 \\
46 \bottomrule
47 \end{tabular}
48 \end{table}
49
50 EOT
51 ;
52
53 my $output = $table->generate_string;
54
55 is_deeply(
56 [ split( "\n", $output ) ],
57 [ split( "\n", $expected_output ) ],
58 'is_number works with complicated shortcutted headers and data',
59 );
0 use Test::More tests => 32;
1 use Test::NoWarnings;
2
3 use LaTeX::Table;
4 use English qw( -no_match_vars );
5
6 my $table = LaTeX::Table->new();
7 # font family test 1
8 eval { $table->_add_font_family( { value => 'test' }, 'test' ) };
9 ok( $EVAL_ERROR, 'unknown font family' );
10
11 #font family test 2
12 eval { $table->_add_font_family( { value => 'test' }, 'bf' ) };
13 ok( !$EVAL_ERROR, 'known font family' );
14
15 # callback test 1
16 my $header = [ [ 'a', 'b' ] ];
17 my $data = [ [ '1', '2' ] ];
18
19 $table = LaTeX::Table->new(
20 { header => $header,
21 data => $data,
22 callback => [],
23 }
24 );
25
26 eval { $table->generate_string; };
27 like(
28 $EVAL_ERROR,
29 qr{Invalid usage of option callback: Not a code reference\.},
30 'callback not a code reference'
31 ) || diag $EVAL_ERROR;
32
33 # callback test 2
34 $table->set_callback( sub { return 'a'; } );
35
36 eval { $table->generate_string; };
37 ok( !$EVAL_ERROR, 'no error with valid callback' ) || diag $EVAL_ERROR;
38
39
40 # xentrystretch test 1
41 $table = LaTeX::Table->new(
42 { header => $header,
43 data => $data,
44 type => 'xtab',
45 xentrystretch => 'a',
46 }
47 );
48
49 eval { $table->generate_string; };
50 like(
51 $EVAL_ERROR,
52 qr{Invalid usage of option xentrystretch: Not a number: a\.},
53 'xentrystretch not a number'
54 ) || diag $EVAL_ERROR;
55
56 # xentrystretch test 2
57 $table->set_xentrystretch(0.8);
58 eval { $table->generate_string; };
59 ok( !$EVAL_ERROR, 'no error with valid xentrystretch' ) || diag $EVAL_ERROR;
60
61 # theme test 1
62 # xentrystretch test 1
63 $table = LaTeX::Table->new(
64 { header => $header,
65 data => $data,
66 theme => 'Leipzig',
67 }
68 );
69
70 eval { $table->generate_string; };
71 like(
72 $EVAL_ERROR,
73 qr{Invalid usage of option theme: Not known: Leipzig\.},
74 'unknown theme'
75 ) || diag $EVAL_ERROR;
76
77 $table->set_theme('Dresden');
78 eval { $table->generate_string; };
79 ok( !$EVAL_ERROR, 'no error with valid theme' ) || diag $EVAL_ERROR;
80
81 # size tests
82
83 $table = LaTeX::Table->new(
84 { header => $header,
85 data => $data,
86 fontsize => 'HUGE',
87 }
88 );
89
90 eval { $table->generate_string; };
91 like(
92 $EVAL_ERROR,
93 qr{^Invalid usage of option custom_themes: Size not known: HUGE. Valid sizes},
94 'unknown size'
95 ) || diag $EVAL_ERROR;
96 $table->set_fontsize('Huge');
97
98 eval { $table->generate_string; };
99 ok( !$EVAL_ERROR, 'no error with valid size' ) || diag $EVAL_ERROR;
100
101 # header tests
102 $table = LaTeX::Table->new(
103 { header => 'A, B',
104 data => $data,
105 }
106 );
107
108 eval { $table->generate_string; };
109 like(
110 $EVAL_ERROR,
111 qr{Invalid usage of option header: Not an array reference\.},
112 'header is not an array reference'
113 ) || diag $EVAL_ERROR;
114 $table->set_header([ 'A', 'B' ]);
115 eval { $table->generate_string; };
116 like(
117 $EVAL_ERROR,
118 qr{\QInvalid usage of option header: header[0] Not an array reference.},
119 'header[0] is not an array reference'
120 ) || diag $EVAL_ERROR;
121
122 $table->set_header([ [ 'A', ['B'] ] ]);
123 eval { $table->generate_string; };
124 like(
125 $EVAL_ERROR,
126 qr{\QInvalid usage of option header: header[0][1] not a scalar.},
127 'header[0][1] is not a scalar'
128 ) || diag $EVAL_ERROR;
129
130 # data tests
131 $table = LaTeX::Table->new(
132 { header => $header,
133 data => { 'A' => 1, 'B' => 1 },
134 }
135 );
136
137 eval { $table->generate_string; };
138 like(
139 $EVAL_ERROR,
140 qr{Invalid usage of option data: Not an array reference\.},
141 'data is not an array reference'
142 ) || diag $EVAL_ERROR;
143
144 $table->set_data([ [ 'A', 'B'], { 'A' => 1, 'B' => 1 } ]);
145 eval { $table->generate_string; };
146 like(
147 $EVAL_ERROR,
148 qr{\QInvalid usage of option data: data[1] Not an array reference.},
149 'data[1] is not an array reference'
150 ) || diag $EVAL_ERROR;
151
152 $table->set_data([ [ 'A', 'B'], [ 'A', undef ] ]);
153 eval { $table->generate_string; };
154 like(
155 $EVAL_ERROR,
156 qr{Undefined value in data\[1\]\[1\].},
157 'undef value'
158 ) || diag $EVAL_ERROR;
159
160 $table->set_data($data);
161 $table->set_coldef_strategy(1);
162
163 eval { $table->generate_string; };
164 like(
165 $EVAL_ERROR,
166 qr{Invalid usage of option coldef_strategy: Not a hash reference\.},
167 'coldef_strategy not a hash'
168 ) || diag $EVAL_ERROR;
169
170 $table->set_coldef_strategy(['a', 'b']);
171
172 eval { $table->generate_string; };
173 like(
174 $EVAL_ERROR,
175 qr{Invalid usage of option coldef_strategy: Not a hash reference\.},
176 'coldef_strategy not a hash'
177 ) || diag $EVAL_ERROR;
178
179 $table->set_coldef_strategy({
180 URL => qr{ \A \s* http }xms,
181 });
182
183 eval { $table->generate_string; };
184 like(
185 $EVAL_ERROR,
186 qr{^Invalid usage of option coldef_strategy: Missing column attribute URL_COL for URL\.},
187 'Missing column attribute URL_COL for URL.'
188 ) || diag $EVAL_ERROR;
189
190 $table = LaTeX::Table->new(
191 { header => $header,
192 data => $data,
193 width_environment => 'tabularx',
194 }
195 );
196
197 eval { $table->generate_string; };
198 like(
199 $EVAL_ERROR,
200 qr{Invalid usage of option width_environment: Is tabularx and width is unset\. },
201 'unknown width environment'
202 ) || diag $EVAL_ERROR;
203
204 $table = LaTeX::Table->new(
205 { header => $header,
206 data => $data,
207 width_environment => 'tabulary',
208 }
209 );
210
211 eval { $table->generate_string; };
212 like(
213 $EVAL_ERROR,
214 qr{Invalid usage of option width_environment: Is tabulary and width is unset\. },
215 'unknown width environment'
216 ) || diag $EVAL_ERROR;
217
218 $table = LaTeX::Table->new(
219 { header => $header,
220 data => $data,
221 columns_like_header => 2,
222 }
223 );
224
225 eval { $table->generate_string; };
226 like(
227 $EVAL_ERROR,
228 qr{^Invalid usage of option columns_like_header: Not an array reference\.},
229 'columns_like_header not an array reference'
230 ) || diag $EVAL_ERROR;
231
232 $table = LaTeX::Table->new(
233 { header => $header,
234 data => $data,
235 columns_like_header => { 1 => 2 },
236 }
237 );
238
239 eval { $table->generate_string; };
240 like(
241 $EVAL_ERROR,
242 qr{Invalid usage of option columns_like_header: Not an array reference\.},
243 'columns_like_header not an array reference'
244 ) || diag $EVAL_ERROR;
245
246 $table = LaTeX::Table->new(
247 { header => $header,
248 data => $data,
249 columns_like_header => 0,
250 }
251 );
252
253 eval { $table->generate_string; };
254 ok(
255 !$EVAL_ERROR,
256 'columns_like_header 0 is ok'
257 ) || diag $EVAL_ERROR;
258
259 ## resizebox
260
261 $table = LaTeX::Table->new(
262 { header => $header,
263 data => $data,
264 resizebox => 2,
265 }
266 );
267 eval { $table->generate_string; };
268 like(
269 $EVAL_ERROR,
270 qr{Invalid usage of option resizebox: Not an array reference\.},
271 'resizebox not an array reference'
272 ) || diag $EVAL_ERROR;
273
274 $table = LaTeX::Table->new(
275 { header => $header,
276 data => $data,
277 resizebox => { 1 => 2 },
278 }
279 );
280
281 eval { $table->generate_string; };
282 like(
283 $EVAL_ERROR,
284 qr{Invalid usage of option resizebox: Not an array reference\.},
285 'resizebox not an array reference'
286 ) || diag $EVAL_ERROR;
287
288 $table = LaTeX::Table->new(
289 { header => $header,
290 data => $data,
291 resizebox => 0,
292 }
293 );
294
295 eval { $table->generate_string; };
296 ok(
297 !$EVAL_ERROR,
298 'resizebox 0 is ok'
299 ) || diag $EVAL_ERROR;
300
301 $table = LaTeX::Table->new(
302 { header => $header,
303 data => $data,
304 environment => 0,
305 type => 'xtab',
306 }
307 );
308
309
310 eval { $table->generate_string; };
311
312 like(
313 $EVAL_ERROR,
314 qr{Invalid usage of option environment: xtab requires an environment\.},
315 'xtab requires environment'
316 ) || diag $EVAL_ERROR;
317
318 $table = LaTeX::Table->new(
319 { header => $header,
320 data => $data,
321 position => 'htb',
322 type => 'xtab',
323 }
324 );
325
326
327 eval { $table->generate_string; };
328
329 like(
330 $EVAL_ERROR,
331 qr{Invalid usage of option position: xtab does not support position\.},
332 'xtab does not support position'
333 ) || diag $EVAL_ERROR;
334
335 $table = LaTeX::Table->new(
336 { header => $header,
337 data => $data,
338 left => 1,
339 center => 1,
340 }
341 );
342
343 eval { $table->generate_string; };
344
345 like(
346 $EVAL_ERROR,
347 qr{Invalid usage of option center, left, right},
348 'only one allowed'
349 ) || diag $EVAL_ERROR;
350
351 $table = LaTeX::Table->new(
352 { header => $header,
353 data => $data,
354 shortcaption => 'short',
355 maincaption => 'main',
356 }
357 );
358
359 eval { $table->generate_string; };
360
361 like(
362 $EVAL_ERROR,
363 qr{Invalid usage of option maincaption, shortcaption},
364 'only one allowed'
365 ) || diag $EVAL_ERROR;
0 use Test::More tests => 4;
1 use Test::NoWarnings;
2
3 use LaTeX::Table;
4 use English qw( -no_match_vars ) ;
5
6 my $table = LaTeX::Table->new({ filename => 'out.tex',
7 label => 'beercounter',
8 maincaption => 'Beer Counter',
9 caption => 'Number of beers before and after 4pm.',
10 });
11
12 my $test_data = [ [ 1, 2, 4], [ 2, 3 ] ];
13 $table->_calc_data_summary($test_data);
14 my @summary = $table->_get_data_summary();
15 is_deeply(\@summary, ['NUMBER','NUMBER','NUMBER'], 'all integers');
16
17 $test_data = [ [ 'a', 2, 4], [ 'b', 3 ] ];
18 $table->_calc_data_summary($test_data);
19 @summary = $table->_get_data_summary();
20 is_deeply(\@summary, ['DEFAULT','NUMBER','NUMBER'], 'not all integers');
21
22 $test_data = [ [ 'a', 2, ], [ '1', 3 ] ];
23 $table->_calc_data_summary($test_data);
24 @summary = $table->_get_data_summary();
25 is_deeply(\@summary, ['DEFAULT','NUMBER'], 'not all integers');
0 use Test::More tests => 2;
1 use Test::NoWarnings;
2 use English qw( -no_match_vars ) ;
3
4 my $SYNOPSIS = <<'EOT'
5
6 use LaTeX::Table;
7 #use Number::Format qw(:subs); # use mighty CPAN to format values
8
9 my $header = [
10 [ 'Item:2c', '' ],
11 ['\cmidrule(r){1-2}'],
12 [ 'Animal', 'Description', 'Price' ]
13 ];
14
15 my $data = [
16 [ 'Gnat', 'per gram', '13.65' ],
17 [ '', 'each', '0.0173' ],
18 [ 'Gnu', 'stuffed', '92.59' ],
19 [ 'Emu', 'stuffed', '33.33' ],
20 [ 'Armadillo', 'frozen', '8.99' ],
21 ];
22
23
24 my $table = LaTeX::Table->new(
25 {
26 filename => 'prices.tex',
27 maincaption => 'Price List',
28 caption => 'Try our special offer today!',
29 label => 'table:prices',
30 position => 'htb',
31 header => $header,
32 data => $data,
33 }
34 );
35
36 # write LaTeX code in prices.tex
37 $table->generate_string();
38
39 # callback functions help you to format values easily (as
40 # a great alternative to LaTeX packages like rccol)
41 #
42 # Here, the first colum and the header is printed in upper
43 # case and the third colum is formatted with format_price()
44 $table->set_callback(sub {
45 my ($row, $col, $value, $is_header ) = @_;
46 if ($col == 0 || $is_header) {
47 $value = uc $value;
48 }
49 elsif ($col == 2 && !$is_header) {
50 # $value = format_price($value, 2, '');
51 }
52 return $value;
53 });
54
55 print $table->generate_string();
56
57 EOT
58 ;
59
60 eval $SYNOPSIS;
61 ok(!$EVAL_ERROR,"Test Synopsis") || diag $EVAL_ERROR;
62
0 use Test::More tests => 7;
1 use Test::NoWarnings;
2
3 use strict;
4 use warnings;
5
6 use LaTeX::Table;
7 use English qw( -no_match_vars );
8
9 my $header = [ [ 'A', 'B', 'C', ], ];
10 my $data = [
11 [ '123.45678', ' 12345678901234567890', '12345', ],
12 [ '123.45', ' A ', '12345', ],
13 ];
14
15 my $table = LaTeX::Table->new(
16 { header => $header,
17 data => $data,
18 }
19 );
20
21 my $output = $table->generate_string();
22
23 my $expected_output = <<'EOT';
24 \begin{table}
25 \centering
26 \begin{tabular}{llr}
27 \toprule
28 A & B & C \\
29 \midrule
30 123.45678 & 12345678901234567890 & 12345 \\
31 123.45 & A & 12345 \\
32 \bottomrule
33 \end{tabular}
34 \end{table}
35 EOT
36
37 is_deeply(
38 [ split( "\n", $output ) ],
39 [ split( "\n", $expected_output ) ],
40 'three number columns'
41 );
42
43 $table->set_coldef_strategy({
44 NUMBER => qr{\A \s* \d+ \s* \z}xms, # integers only
45 LONG_COL => '>{\raggedright\arraybackslash}p{7cm}', # non-justified
46 });
47
48 $output = $table->generate_string();
49
50 $expected_output = <<'EOT';
51 \begin{table}
52 \centering
53 \begin{tabular}{llr}
54 \toprule
55 A & B & C \\
56 \midrule
57 123.45678 & 12345678901234567890 & 12345 \\
58 123.45 & A & 12345 \\
59 \bottomrule
60 \end{tabular}
61 \end{table}
62 EOT
63
64 is_deeply(
65 [ split( "\n", $output ) ],
66 [ split( "\n", $expected_output ) ],
67 'three number columns'
68 );
69
70 $table->set_coldef_strategy({
71 NUMBER => qr{\A \s* \d+ \s* \z}xms, # integers only
72 NUMBER_MUST_MATCH_ALL => 0,
73 LONG_COL => '>{\raggedright\arraybackslash}p{7cm}', # non-justified
74 });
75
76
77 $output = $table->generate_string();
78
79 $expected_output = <<'EOT';
80 \begin{table}
81 \centering
82 \begin{tabular}{lrr}
83 \toprule
84 A & B & C \\
85 \midrule
86 123.45678 & 12345678901234567890 & 12345 \\
87 123.45 & A & 12345 \\
88 \bottomrule
89 \end{tabular}
90 \end{table}
91 EOT
92
93 is_deeply(
94 [ split( "\n", $output ) ],
95 [ split( "\n", $expected_output ) ],
96 'three number columns'
97 );
98
99 $data = [
100 [ '123.45678', ' 12345678901123456789011234567890 ', '12345', ],
101 [ '123.45', ' 1234567898 ', '12345', ],
102 ];
103 $table = LaTeX::Table->new(
104 { header => $header,
105 data => $data,
106 }
107 );
108
109 $table->set_coldef_strategy({
110 NUMBER => qr{\A \s* \d+ \s* \z}xms, # integers only
111 LONG_COL => '>{\raggedright\arraybackslash}p{7cm}', # non-justified
112 });
113
114
115 $output = $table->generate_string();
116
117 $expected_output = <<'EOT';
118 \begin{table}
119 \centering
120 \begin{tabular}{lrr}
121 \toprule
122 A & B & C \\
123 \midrule
124 123.45678 & 12345678901123456789011234567890 & 12345 \\
125 123.45 & 1234567898 & 12345 \\
126 \bottomrule
127 \end{tabular}
128 \end{table}
129 EOT
130
131 is_deeply(
132 [ split( "\n", $output ) ],
133 [ split( "\n", $expected_output ) ],
134 'LONG NUMBER Is NUMBER'
135 );
136
137 # not a number anymore
138 $table->set_data([
139 [ '123.45678', ' 1234567890 1234567890 1234567890', '12345', ],
140 [ '123.45', ' 1234567898.122 ', '12345', ],
141 ]);
142
143 $output = $table->generate_string();
144
145 $expected_output = <<'EOT';
146 \begin{table}
147 \centering
148 \begin{tabular}{l>{\raggedright\arraybackslash}p{7cm}r}
149 \toprule
150 A & B & C \\
151 \midrule
152 123.45678 & 1234567890 1234567890 1234567890 & 12345 \\
153 123.45 & 1234567898.122 & 12345 \\
154 \bottomrule
155 \end{tabular}
156 \end{table}
157 EOT
158
159 is_deeply(
160 [ split( "\n", $output ) ],
161 [ split( "\n", $expected_output ) ],
162 'LONG Is LONG'
163 );
164
165 $table->set_coldef_strategy({
166 URL => qr{\A \s* http }xms,
167 URL_COL => 'U', # centered
168 });
169
170 $table->set_data([
171 [ '123.45678', ' http://www.google.com', '12345', ],
172 [ '123.45', ' http://www.slashdot.org ', '12345', ],
173 ]);
174
175 $output = $table->generate_string();
176
177 $expected_output = <<'EOT';
178 \begin{table}
179 \centering
180 \begin{tabular}{lUr}
181 \toprule
182 A & B & C \\
183 \midrule
184 123.45678 & http://www.google.com & 12345 \\
185 123.45 & http://www.slashdot.org & 12345 \\
186 \bottomrule
187 \end{tabular}
188 \end{table}
189 EOT
190
191 is_deeply(
192 [ split( "\n", $output ) ],
193 [ split( "\n", $expected_output ) ],
194 'new column type'
195 );
196
0 use Test::More tests => 4;
1 use Test::NoWarnings;
2
3 use LaTeX::Table;
4
5 my $header = [ [ 'A', 'B', 'C' ], [ 'a', 'b', 'c' ] ];
6 my $data = [
7 [ 'Marge', 'Homer', 'Bart' ],
8 [ 'Marge', 'Homer', 'Bart' ],
9 [ 'Marge', 'Homer', 'Bart' ],
10 ];
11
12 my $table = LaTeX::Table->new(
13 { header => $header,
14 data => $data,
15 theme => 'Dresden',
16 callback => sub {
17 my ( $row, $col, $value, $is_header ) = @_;
18 if ( $row == 1 && !$is_header ) {
19 return lc $value;
20 }
21 if ( $row == 0 && $is_header ) {
22 return lc $value;
23 }
24 if ( ( $row + $col ) % 2 == 0 ) {
25 return uc $value;
26 }
27 return 'foo';
28 },
29 }
30 );
31 my $expected_output = <<'EOT'
32 \begin{table}
33 \centering
34 \begin{tabular}{|l||l|l|}
35 \hline
36 \multicolumn{1}{|c||}{\textbf{a}} & \multicolumn{1}{c|}{\textbf{b}} & \multicolumn{1}{c|}{\textbf{c}} \\
37 \multicolumn{1}{|c||}{\textbf{foo}} & \multicolumn{1}{c|}{\textbf{B}} & \multicolumn{1}{c|}{\textbf{foo}} \\
38 \hline
39 \hline
40 MARGE & foo & BART \\
41 marge & homer & bart \\
42 MARGE & foo & BART \\
43 \hline
44 \end{tabular}
45 \end{table}
46 EOT
47 ;
48 my $output = $table->generate_string;
49
50 is_deeply(
51 [ split( "\n", $output ) ],
52 [ split( "\n", $expected_output ) ],
53 'callback seems to work with words',
54 );
55
56 $header = [ [ 'A:2c', 'C' ], [ 'a', 'b', 'c' ] ];
57 $table = LaTeX::Table->new(
58 { header => $header,
59 data => $data,
60 callback => sub {
61 my ( $row, $col, $value, $is_header ) = @_;
62 if ( $is_header ) {
63 return uc $value;
64 }
65 },
66 theme => 'Zurich',
67 }
68 );
69
70 $expected_output = <<'EOT'
71 \begin{table}
72 \centering
73 \begin{tabular}{lll}
74 \toprule
75 \multicolumn{2}{c}{\textbf{A}} & \multicolumn{1}{c}{\textbf{C}} \\
76 \textbf{A} & \multicolumn{1}{c}{\textbf{B}} & \multicolumn{1}{c}{\textbf{C}} \\
77 \midrule
78 0 & 0 & 0 \\
79 0 & 0 & 0 \\
80 0 & 0 & 0 \\
81 \bottomrule
82 \end{tabular}
83 \end{table}
84
85 EOT
86 ;
87 $output = $table->generate_string;
88
89 is_deeply(
90 [ split( "\n", $output ) ],
91 [ split( "\n", $expected_output ) ],
92 'callback seems to work with uc headers and shortcuts',
93 );
94
95
96 $header = [ [ 'A:3c'], ['A:2c', 'B'], ['A', 'B', 'C'], ];
97 $data = [ [ 'D:3c'], ['D:2c', 'E'], ['D', 'E', 'F'], ];
98
99 $table = LaTeX::Table->new(
100 { header => $header,
101 data => $data,
102 callback => sub {
103 my ( $row, $col, $value, $is_header ) = @_;
104 if ( $col == 0) {
105 return 'X' . $value;
106 }
107 elsif ( $col == 1) {
108 return 'Y' . $value;
109 }
110 else {
111 return 'Z' . $value;
112 }
113 },
114 theme => 'Zurich',
115 }
116 );
117
118 $output = $table->generate_string;
119
120 $expected_output = <<'EOT'
121 \begin{table}
122 \centering
123 \begin{tabular}{lll}
124 \toprule
125 \multicolumn{3}{c}{\textbf{XA}} \\
126 \multicolumn{2}{c}{\textbf{XA}} & \multicolumn{1}{c}{\textbf{ZB}} \\
127 \textbf{XA} & \multicolumn{1}{c}{\textbf{YB}} & \multicolumn{1}{c}{\textbf{ZC}} \\
128 \midrule
129 \multicolumn{3}{c}{XD} \\
130 \multicolumn{2}{c}{XD} & ZE \\
131 XD & YE & ZF \\
132 \bottomrule
133 \end{tabular}
134 \end{table}
135
136 EOT
137 ;
138
139 $output = $table->generate_string;
140
141 is_deeply(
142 [ split( "\n", $output ) ],
143 [ split( "\n", $expected_output ) ],
144 'callback works with complicated shortcutted headers and data',
145 );
0 use Test::More tests => 9;
1 use Test::NoWarnings;
2
3 use lib 't/lib';
4 use LaTeX::Table;
5
6 my $themes = {
7 'Leipzig' => {
8 'HEADER_FONT_STYLE' => 'sc',
9 'HEADER_CENTERED' => 1,
10 'VERTICAL_RULES' => [ 1, 2, 1 ],
11 'HORIZONTAL_RULES' => [ 1, 2, 0 ],
12 },
13 'Leipzig2' => {
14 'HEADER_CENTERED' => 1,
15 'VERTICAL_RULES' => [ 1, 2, 1 ],
16 'HORIZONTAL_RULES' => [ 1, 2, 0 ],
17 },
18 'Leipzig3' => {
19 'VERTICAL_RULES' => [ 1, 2, 1 ],
20 'HORIZONTAL_RULES' => [ 1, 2, 0 ],
21 },
22 'Leipzig3b' => {
23 'HEADER_CENTERED' => 0,
24 'VERTICAL_RULES' => [ 1, 2, 1 ],
25 'HORIZONTAL_RULES' => [ 1, 2, 0 ],
26 'BOOKTABS' => 0,
27 },
28 };
29
30 my $test_header = [ [ 'A', 'B', 'C' ], ];
31 my $test_data = [ [ '1', 'w', 'x' ], [], [ '2', 'y', 'z' ], ];
32
33 my $table = LaTeX::Table->new(
34 { environment => 'sidewaystable',
35 caption => 'Test Caption',
36 maincaption => 'Test',
37 header => $test_header,
38 data => $test_data,
39 custom_themes => $themes,
40 theme => 'Leipzig',
41 }
42 );
43
44 my $expected_output = <<'EOT'
45 \begin{sidewaystable}
46 \centering
47 \begin{tabular}{|r||l|l|}
48 \hline
49 \multicolumn{1}{|c||}{\textsc{A}} & \multicolumn{1}{c|}{\textsc{B}} & \multicolumn{1}{c|}{\textsc{C}} \\
50 \hline
51 \hline
52 1 & w & x \\
53 \hline
54 2 & y & z \\
55 \hline
56 \end{tabular}
57 \caption[Test]{Test. Test Caption}
58 \end{sidewaystable}
59 EOT
60 ;
61
62 my $output = $table->generate_string();
63 my @expected_output = split "\n", $expected_output;
64
65 is_deeply(
66 [ split( "\n", $output ) ],
67 \@expected_output,
68 'without table environment'
69 );
70
71 $table->set_theme('Leipzig2');
72 $table->set_environment('table');
73 $output = $table->generate_string();
74
75 $expected_output = <<'EOT'
76 \begin{table}
77 \centering
78 \begin{tabular}{|r||l|l|}
79 \hline
80 \multicolumn{1}{|c||}{A} & \multicolumn{1}{c|}{B} & \multicolumn{1}{c|}{C} \\
81 \hline
82 \hline
83 1 & w & x \\
84 \hline
85 2 & y & z \\
86 \hline
87 \end{tabular}
88 \caption[Test]{Test. Test Caption}
89 \end{table}
90 EOT
91 ;
92
93 @expected_output = split "\n", $expected_output;
94
95 is_deeply(
96 [ split( "\n", $output ) ],
97 \@expected_output,
98 'without header font'
99 );
100
101 $table->set_theme('Leipzig3');
102 $output = $table->generate_string();
103
104 $expected_output = <<'EOT'
105 \begin{table}
106 \centering
107 \begin{tabular}{|r||l|l|}
108 \hline
109 A & B & C \\
110 \hline
111 \hline
112 1 & w & x \\
113 \hline
114 2 & y & z \\
115 \hline
116 \end{tabular}
117 \caption[Test]{Test. Test Caption}
118 \end{table}
119 EOT
120 ;
121 @expected_output = split "\n", $expected_output;
122
123 is_deeply(
124 [ split( "\n", $output ) ],
125 \@expected_output,
126 'theme, without header centered'
127 );
128
129 $table->set_theme('Leipzig3b');
130 $output = $table->generate_string();
131 is_deeply(
132 [ split( "\n", $output ) ],
133 \@expected_output,
134 'theme, without header centered'
135 );
136
137 $table->set_theme('Zurich');
138 $output = $table->generate_string();
139
140 $expected_output = <<'EOT'
141 \begin{table}
142 \centering
143 \begin{tabular}{lll}
144 \toprule
145 \textbf{A} & \multicolumn{1}{c}{\textbf{B}} & \multicolumn{1}{c}{\textbf{C}} \\
146 \midrule
147 1 & w & x \\
148 \midrule
149 2 & y & z \\
150 \bottomrule
151 \end{tabular}
152 \caption[Test]{Test. Test Caption}
153 \end{table}
154 EOT
155 ;
156 @expected_output = split "\n", $expected_output;
157
158 is_deeply(
159 [ split( "\n", $output ) ],
160 \@expected_output,
161 'standard theme'
162 );
163
164 $table->search_path( add => 'MyThemes' );
165 $table->set_theme('Erfurt');
166
167 $output = $table->generate_string();
168
169 $expected_output = <<'EOT'
170 \begin{table}
171 \centering
172 \begin{tabular}{lll}
173 \toprule
174 \textsc{A} & \multicolumn{1}{c}{\textsc{B}} & \multicolumn{1}{c}{\textsc{C}} \\
175 \midrule
176 1 & w & x \\
177 \midrule
178 2 & y & z \\
179 \bottomrule
180 \end{tabular}
181 \caption[Test]{Test. Test Caption}
182 \end{table}
183 EOT
184 ;
185 @expected_output = split "\n", $expected_output;
186
187 is_deeply(
188 [ split( "\n", $output ) ],
189 \@expected_output,
190 'custom search path'
191 );
192
193 is_deeply($table->get_available_themes->{Erfurt}->{RULES_CMD},[ '\toprule',
194 '\midrule', '\midrule', '\bottomrule' ], 'BOOKTABS shortcut' );
195
196
197 $test_header = [ [ 'head1', 'head2', 'head3', 'head4' ], ];
198 $test_data = [
199 [ 'row1', 'row1', 'row1', 'row1' ],
200 [ 'row2', 'row2', 'row2', 'row2' ],
201 [ 'row3', 'row3', 'row3', 'row3' ],
202 [ 'row4', 'row4', 'row4', 'row4' ],
203 ];
204
205 my $custom_template = << 'EOT'
206 [%IF CONTINUED %]\addtocounter{table}{-1}[% END %][% COLORDEF_CODE %][% IF
207 ENVIRONMENT %]\begin{[% ENVIRONMENT %][% IF STAR %]*[% END %]}[% IF POSITION %][[% POSITION %]][% END %][% END %]
208 \processtable{[% IF CAPTION %][% CAPTION %][% END %][% IF CONTINUED %] [% CONTINUEDMSG %][% END %][% IF LABEL %]\label{[% LABEL %]}[% END %]}
209 {\begin{[% TABULAR_ENVIRONMENT %]}{[% COLDEF %]}
210 [% HEADER_CODE %][% DATA_CODE %]\end{[% TABULAR_ENVIRONMENT %]}}{[% FOOTTABLE %]}
211 [% IF ENVIRONMENT %]\end{table}[% END %]
212 EOT
213 ;
214
215 $table = LaTeX::Table->new(
216 {
217 caption => 'This is table caption',
218 label => 'Tab:01',
219 foottable => 'This is a footnote',
220 position => '!t',
221 header => $test_header,
222 data => $test_data,
223 custom_themes => $themes,
224 theme => 'Oxford',
225 custom_template => $custom_template,
226 }
227 );
228
229 $expected_output = <<'EOT'
230 \begin{table}[!t]
231 \processtable{This is table caption\label{Tab:01}}
232 {\begin{tabular}{llll}
233 \toprule
234 head1 & head2 & head3 & head4 \\
235 \midrule
236 row1 & row1 & row1 & row1 \\
237 row2 & row2 & row2 & row2 \\
238 row3 & row3 & row3 & row3 \\
239 row4 & row4 & row4 & row4 \\
240 \botrule
241 \end{tabular}}{This is a footnote}
242 \end{table}
243 EOT
244 ;
245
246 @expected_output = split "\n", $expected_output;
247 $output = $table->generate_string();
248
249 is_deeply(
250 [ split( "\n", $output ) ],
251 \@expected_output,
252 'custom search path'
253 );
0 BEGIN { our $WARNMSG; $SIG{'__WARN__'} = sub { $WARNMSG = $_[0]; } };
1
2 use Test::More tests => 4;
3
4 use LaTeX::Table;
5
6
7 my $test_header = [ [ 'A', 'B', 'C' ], ];
8 my $test_data = [ [ '1', 'w', 'x' ], [], [ '2', 'y', 'z' ], ];
9
10 my $table = LaTeX::Table->new({ tablepos => 'ht',
11 table_environment => 'sidewaystable',
12 tabledef => 'lcc',
13 theme => 'Zurich',
14 });
15
16 $table->generate_string($test_header, $test_data);
17 like($WARNMSG, qr{DEPRECATED. Use options header and data instead},
18 'DEPRECATED warning');
19
20 my $expected_output = <<'EOT'
21 \begin{sidewaystable}[ht]
22 \centering
23 \begin{tabular}{lcc}
24 \toprule
25 \textbf{A} & \multicolumn{1}{c}{\textbf{B}} & \multicolumn{1}{c}{\textbf{C}} \\
26 \midrule
27 1 & w & x \\
28 \midrule
29 2 & y & z \\
30 \bottomrule
31 \end{tabular}
32 \end{sidewaystable}
33 EOT
34 ;
35
36 my $output = $table->generate_string();
37 my @expected_output = split "\n", $expected_output;
38
39 is_deeply(
40 [ split( "\n", $output ) ],
41 \@expected_output,
42 'with < 0.1.0 API'
43 );
44
45 $table = LaTeX::Table->new({ tablepos => 'ht',
46 header => $test_header,
47 data => [ [ '1', 'w', 'x' ], [], [ '2.1',
48 'y12345', 'z' ], ],
49 theme => 'Zurich',
50 });
51
52 $table->set_tabledef_strategy({
53 IS_A_NUMBER => qr{\A \d+ \z}xms,
54 IS_LONG => 5,
55 LONG_COL => 'p{5cm}',
56 DEFAULT_X => 'c',
57 DEFAULT => 'r',
58 });
59
60 $expected_output = <<'EOT'
61 \begin{table}[ht]
62 \centering
63 \begin{tabular}{lp{5cm}r}
64 \toprule
65 \textbf{A} & \multicolumn{1}{c}{\textbf{B}} & \multicolumn{1}{c}{\textbf{C}} \\
66 \midrule
67 1 & w & x \\
68 \midrule
69 2.1 & y12345 & z \\
70 \bottomrule
71 \end{tabular}
72 \end{table}
73 EOT
74 ;
75
76 $output = $table->generate_string();
77
78 is_deeply(
79 [ split( "\n", $output ) ],
80 [ split( "\n", $expected_output ) ],
81 'three number columns'
82 );
83
84 $table->set_width('300pt');
85 $table->set_width_environment('tabularx');
86
87 $expected_output = <<'EOT'
88 \begin{table}[ht]
89 \centering
90 \begin{tabularx}{300pt}{lXc}
91 \toprule
92 \textbf{A} & \multicolumn{1}{c}{\textbf{B}} & \multicolumn{1}{c}{\textbf{C}} \\
93 \midrule
94 1 & w & x \\
95 \midrule
96 2.1 & y12345 & z \\
97 \bottomrule
98 \end{tabularx}
99 \end{table}
100 EOT
101 ;
102
103 $output = $table->generate_string();
104
105 is_deeply(
106 [ split( "\n", $output ) ],
107 [ split( "\n", $expected_output ) ],
108 'three number columns'
109 );
0 package MyThemes::Custom;
1 use Moose;
2
3 with 'LaTeX::Table::Themes::ThemeI';
4
5 sub _definition {
6 return {
7 'Erfurt' => {
8 'HEADER_FONT_STYLE' => 'sc',
9 'HEADER_CENTERED' => 1,
10 'STUB_ALIGN' => q{l},
11 'VERTICAL_RULES' => [ 0, 0, 0 ],
12 'HORIZONTAL_RULES' => [ 1, 1, 0 ],
13 'BOOKTABS' => 1,
14 },
15 'Oxford' => {
16 'STUB_ALIGN' => q{l},
17 'VERTICAL_RULES' => [ 0, 0, 0 ],
18 'HORIZONTAL_RULES' => [ 1, 1, 0 ],
19 'RULES_CMD' => [ '\toprule', '\midrule', '\midrule', '\botrule' ],
20 }
21 };
22 }
23
24 1;
25
26 # vim: ft=perl sw=4 ts=4 expandtab
0 #!perl
1
2 use strict;
3 use warnings;
4 use File::Spec;
5 use Test::More;
6 use English qw(-no_match_vars);
7
8 if ( not $ENV{TEST_AUTHOR} ) {
9 my $msg = 'Author test. Set $ENV{TEST_AUTHOR} to a true value to run.';
10 plan( skip_all => $msg );
11 }
12
13 eval { require Test::Perl::Critic; };
14
15 if ( $EVAL_ERROR ) {
16 my $msg = 'Test::Perl::Critic required to criticise code';
17 plan( skip_all => $msg );
18 }
19
20 my $rcfile = File::Spec->catfile( 't', 'perlcriticrc' );
21 Test::Perl::Critic->import( -profile => $rcfile );
22 all_critic_ok();
0 severity=1
1 verbose=11
2
3 [-Documentation::RequirePodSections]
4
5 [Miscellanea::RequireRcsKeywords]
6 keywords = Date Author Revision
7
8 [-ValuesAndExpressions::RequireInterpolationOfMetachars]
9
10 [InputOutput::RequireBriefOpen]
11 lines = 15
0 #!perl -T
1
2 use Test::More;
3 eval "use Test::Pod::Coverage 1.04";
4 plan skip_all => "Test::Pod::Coverage 1.04 required for testing POD coverage" if $@;
5 my $trustme = { trustme =>
6 [qr/^(close|open|BUILD|START|meta|invalid_option_usage)$|^set_|^get_|^has_/] };
7 all_pod_coverage_ok($trustme);
0 use Test::More;
1 eval "use Test::Pod 1.14";
2 plan skip_all => "Test::Pod 1.14 required for testing POD" if $@;
3 all_pod_files_ok();