I'm trying to create a table in PDF format using PDF::Table in perl.
However, it seem to not read my header/cols/rows settings.
Here's my code for the table:
use PDF::API2;
use PDF::Table;
my $pdftable = new PDF::Table;
my $pdf = PDF::API2->new();
my $page = $pdf->page;
#data
my $some_data =[
["1","1","1","1","1","1","1"],
["2","2","2","2","2","2","2"],
["2","2","2","2","2","2","2"],
["2","2","2","2","2","2","2"],
["2","2","2","2","2","2","2"],# x 100 time to have pages
];
#build the table layout
$pdftable->table(
$pdf,
$page,
$some_data,
x => 5,
w => 600,
start_y => 750,
next_y => 750,
start_h => 700,
next_h => 700,
# some optional params
font_size => 8,
border => 0,
background_color_odd => "white",
background_color_even => "lightblue",
header_props => $hdr_props, # see section HEADER ROW PROPERTIES
);
$hdr_props =
{
# This param could be a pdf core font or user specified TTF.
# See PDF::API2 FONT METHODS for more information
font => $pdf->corefont("Times", -encoding => "utf8"),
font_size => 10,
font_color => '#006666',
bg_color => 'yellow',
repeat => 1, # 1/0 eq On/Off if the header row should be repeated to every new page
};
print "Content-Type: application/pdf;\n\n";
binmode(STDOUT);
print $pdf->stringify;
It should make the first row as header by default but the output shows no header properties being set on the first row. And there is no header shown for all pages.
Any help will be appreciated.
I did not run your code.
You are referencing $hdr_props before the variable is filled. Perl does not work that way, you need to order definitions properly.
Add use strict; use warnings FATAL => 'all'; to the top of your programs and Perl will alert you about mistakes like this.
theres no warnings at all, and i followed daxim to put the $hdr_props to top first but it still would not read in the header settings.
The documentation says that header_props needs to be a hash reference, so:
header_props => \$hdr_props, # see section HEADER ROW PROPERTIES
I ran into a similar problem. However, daxim is right, you should also order your code as he suggested.
Related
I am trying to create an Open Office document using PERL and OpenOffice::OODoc, and I wish for the resulting document to be in the landscape orientation.
I tried going through the OpenOffice::OODoc::Styles, and the best I got is: switchPageOrientation(page); but I don't know what page is.
So I put together the following code:
#!/usr/bin/perl -w
use strict;
use Data::Dumper;
use OpenOffice::OODoc;
my $docFile = "../resources/landscape.odt";
my $doc = odfDocument( file => $docFile,
create => 'text' );
my $pageLayout = $doc->updatePageLayout(
"LandscapeStyle",
properties => {
'fo:margin-bottom' => '0.7874in',
'fo:page-width' => '11in',
'style:footnote-max-height' => '0in',
'style:shadow' => 'none',
'fo:margin-left' => '0.7874in',
'fo:margin-right' => '0.7874in',
'fo:page-height' => '8.5in',
'style:num-format' => '1',
'style:print-orientation' => 'landscape',
'style:writing-mode' => 'lr-tb',
'fo:margin-top' => '0.7874in'
}
);
$doc->switchPageOrientation($pageLayout);
$doc->appendParagraph( text => "Testing",
style => $pageLayout );
$doc->save;
print "\"$docFile\" is saved.\n";
print "Done.";
exit 0;
The Output is:
Odd number of elements in hash assignment at C:/Strawberry/perl/site/lib/OpenOffice/OODoc/Styles.pm line 1301.
Use of uninitialized value in list assignment at C:/Strawberry/perl/site/lib/OpenOffice/OODoc/Styles.pm line 1301.
"../resources/landscape.odt" is saved.
Done.`
The document is created but not in landscape, rather within the regular portrait orientation.
Does anyone know what page is, and how I can get it to change my document?
Any ideas?
I am having an issue getting my text validation to work properly. Basically I have 2 entry boxes, one to enter the name of a branch in CVS and the other to enter a directory name. I want my program to validate the text in each box whenever it is changed.
To do this, the documentation online says to use the "key" option to validate the entry whenever a keystroke changes the entry box's contents. The problem is, when I use the "key" option and then run the program, when I type into the entry boxes no text appears.
My code is shown below:
use strict;
use warnings;
use Tkx;
# Initialize BRANCH and DIRECTORY
my ($BRANCH, $DIRECTORY) = ();
# DEFINE DISPLAY OBJECTS ###########################################################################
# Define main window
my $main_window = Tkx::widget->new('.');
# Define content frame
my $content_frame = $main_window->new_ttk__frame(-padding => '5 5 5 5');
# Define labels
my $branch_label = $content_frame->new_ttk__label(-text => 'Branch' );
my $directory_label = $content_frame->new_ttk__label(-text => 'Directory');
# Define entry boxes
my $branch_entry = $content_frame->new_ttk__entry(-width => 20, -textvariable => \$BRANCH , -validate => 'key', -validatecommand => \&check_state);
my $directory_entry = $content_frame->new_ttk__entry(-width => 20, -textvariable => \$DIRECTORY, -validate => 'key', -validatecommand => \&check_state);
# Define buttons
my $generate_list_button = $content_frame->new_ttk__button(-text => 'Generate', -state => 'disabled', -command => \&generate_list);
# POSITION DISPLAY OBJECTS #########################################################################
# Position content frame
$content_frame->g_grid(-column => 0, -row => 0);
# Position labels
$branch_label ->g_grid(-column => 0, -row => 0);
$directory_label->g_grid(-column => 0, -row => 1);
# Position entry boxes
$branch_entry ->g_grid(-column => 1, -row => 0);
$directory_entry->g_grid(-column => 1, -row => 1);
# Position buttons
$generate_list_button->g_grid(-column => 0, -row => 2, -columnspan => 2);
# Add padding
for my $child (Tkx::SplitList($content_frame->g_winfo_children)) {
Tkx::grid_configure($child, -padx => 5, -pady => 5);
}
# Check the state of the program
sub check_state {
# Check conditions are met to enable generate_list
if ($BRANCH && $DIRECTORY) {
if (-d $DIRECTORY) {
$generate_list_button->state('!disabled');
} else {
$generate_list_button->state('disabled');
}
} else {
$generate_list_button->state('disabled');
}
return 0;
}
Tkx::MainLoop();
If I change "key" to something else (like focusout) it appears to work correctly. But I would really like it to validate after every keystroke instead of just when the focus is taken out of the entry box. Why doesn't this work?
Your check_state subroutine always returns 0 which means "validation failed" and prevents
the text from being entered. Since you aren't really validating the text -- just using the validation mechanism to trigger state updates to related widgets -- you should return 1 (unconditionally) instead. See validatecommand in the (Tcl) Tk documentation for more details.
The subroutines returning 0 turned out to be only half the problem. Once I fixed that the entry validation was not acting properly. What was happening was every time it tried to validate the entry it would actually be validating the previous entry.
ex:
If you typed in "/somedirectory" it would try to validate on every keystroke, after the last keystroke of "y" it would get the value of $DIRECTORY and validate against it. The problem was that at this point $DIRECTORY would be equal to "/somedirector"
To solve this issue I had to do a little digging so I wanted to post my findings in case someone else ran into this same issue.
The solution was to use Tkx::Ev() to get the "current" value of the entry as it was being entered.
(Tkx::Ev(%P) gets the newly entered value so the validation will work properly)
# Define the entry box
my $directory_entry = $content_frame->new_ttk__entry(
-width => 20,
-textvariable => \$DIRECTORY,
-validate => 'key',
-validatecommand => [\&check_dir, Tkx::Ev('%P')],
);
# Validate the entry box
sub check_dir {
# Unpack input arguments
my ($P) = #_;
if (-d $P) {
# Do something here
} else {
# Do something else here
}
return 1;
}
I am new in Perl and also RRDs.
I have tried to implement a simple example, and although it seems that is operating correctly the output is not displayed. The pictures are produced normally but there is no data in the graphs.
I have been following the CPAN documentation for implementation RRD::Simple and theoretically I am doing something wrong. I tried to debug the code and it seems fine, but when it comes to print the graphs there is no data.
#!/usr/bin/perl
use strict;
use warnings;
use RRD::Simple ();
use Data::Dumper;
$| = 1; # Flush the output
my ($rrd, $unixtime, $file);
$file = "perl.txt";
my $path = '/home/os/Desktop/Test_Perl/';
my $period = '3years';
my $rrdfile = 'myfile.rrd';
while (sleep 15) {
open(FH, ">>", $file) || die "Unable to open $file: $!\n";
my $range = 50;
my $minimum = 100;
my $random_number_in = int(rand($range)) + $minimum;
my $random_number_out = int(rand($range)) + $minimum;
my $random_number_sec = int(rand($range)) + $minimum;
# Create an interface object
$rrd = RRD::Simple->new(
file => $rrdfile,
cf => [qw( AVERAGE MIN MAX LAST )],
#default_dstype => "DERIVE",
);
unless (-e $rrdfile) {
# Create a new RRD file with 3 data sources called
# bytesIn, bytesOut and faultsPerSec.
$rrd->create(
$period,
step => 5, # 5 sec interval
bytesIn => "GAUGE",
bytesOut => "GAUGE",
faultsPerSec => "GAUGE"
);
}
# Put some arbitary data values in the RRD file for the same
# 3 data sources called bytesIn, bytesOut and faultsPerSec.
$rrd->update(
bytesIn => $random_number_in,
bytesOut => $random_number_out,
faultsPerSec => $random_number_sec
);
print FH "This is the bytes_in: $random_number_in\n";
print FH "This is the bytes_out: $random_number_out\n";
print FH "This is the bytes_sec: $random_number_sec\n";
# Generate graphs:
# /home/os/Desktop/Test_Perl/myfile-hourly.png, /home/os/Desktop/Test_Perl/myfile-daily.png
# /home/os/Desktop/Test_Perl/myfile-weekly.png, /home/os/Desktop/Test_Perl/myfile-monthly.png
my %rtn = $rrd->graph(
$rrdfile,
destination => $path,
basename => "my_graph",
timestamp => "both", # graph, rrd, both or none
periods => [qw(hour day week month)], # omit to generate all graphs
sources => [qw(bytesIn bytesOut faultsPerSec)],
source_colors => [qw(ff0000 aa3333 000000)],
source_labels => [("Bytes In", "Bytes Out", "Faults Per Second")],
source_drawtypes => [qw(LINE1 AREA LINE)],
line_thickness => 2,
extended_legend => 1,
title => "Network Interface eth0",
vertical_label => "Bytes/Faults",
width => 800,
height => 500,
interlaced => "", # If images are interlaced they become visible to browsers more quickly
);
printf("Created %s\n", join(", ", map { $rtn{$_}->[0] } keys %rtn));
# Return information about an RRD file
my $info = $rrd->info($rrdfile); # This method will return a complex data structure containing details about the RRD file, including RRA and data source information.
print Data::Dumper::Dumper($info);
my #sources = $rrd->sources($rrdfile);
my $seconds = $rrd->retention_period($rrdfile); # This method will return the maximum period of time (in seconds) that the RRD file will store data for.
# Get unixtime of when RRD file was last updated
$unixtime = $rrd->last($rrdfile);
print FH "myfile.rrd was last updated at " . scalar(localtime($unixtime)) . "\n";
# Get list of data source names from an RRD file
my #dsnames = $rrd->sources;
print "Available data sources: " . join(", ", #dsnames) . "\n";
my $heartbeat_In = $rrd->heartbeat($rrdfile, "bytesIn");
my $heartbeat_Out = $rrd->heartbeat($rrdfile, "bytesOut");
my $heartbeat_sec = $rrd->heartbeat($rrdfile, "faultsPerSec"); # This method will return the current heartbeat of a data source.
printf "This is the heartbeat_in: %s\n", $heartbeat_In;
my #rtn_In = $rrd->heartbeat($rrdfile, "bytesIn", 10);
my #rtn_Out = $rrd->heartbeat($rrdfile, "bytesOut", 10);
my #rtn_sec = $rrd->heartbeat($rrdfile, "faultsPerSec", 10); # This method will set a new heartbeat of a data source.
close(FH);
}
Part of the output:
'myfilerrd' => {
'last_ds' => 'U',
'value' => undef,
'min' => '0',
'max' => undef,
'minimal_heartbeat' => 120,
'index' => 3,
'type' => 'DERIVE',
'unknown_sec' => 15
}
I do not understand why the value is undefined?
After 3-4 days of testing and searching over the Internet for more information I just found the answer to my problem. RRD is a very simple to use tool but very very powerful. I would recommend anybody to use it through Perl especially with RRD::Simple module is very easy.
Answer:
I was adjusting the heart beat of my RRD to 10 sec, while my step (data collection time) is 300 by default. If the user do not specify the step "sampling frequency" by default the system will use 300. In result the graph takes 0 values so there is not output. More information and very nice analysis can be found here HeartBeat
Based on my experimentation, I found that since I am using a while loop inside the create function I have to first give the command:
my $rrd = RRD::Simple->new( file => "myfile.rrd" );
and as a second step I had to kill the process and set the step by entering the command:
my $rrd = RRD::Simple->new(
file => "myfile.rrd",
step => 50 );
Based on my experimentation I found that I had to remove this block of code below had to be added to the file as a second step. First had to make the creation and then add it on my loop. This is because initially the "myfile.rrd" has to be created with all the settings, before the user start modifying them.
unless (-f "myfile.rrd") {
$rrd->create(
step => 50,
bytesIn => "GAUGE",
bytesOut => "GAUGE",
faultsPerSec => "COUNTER"
);
}
Another point that worth mentioning here is that by default RRD Data Source (DS) is set to GAUGE. More information can be found here RRDtool
The Perl module can be found easily CPAN RRD::Simple which provides analysis and extra "features" that you can add to your code.
In conclusion RRD::Simple is very simple, it can be executed by copy-paste into your program. Any further modifications (e.g sample rates, Average/Max/Min values etc.) need a bit of reading upon but definitely worth the effort. Unfortunately there is not much of examples online so some testing need it to be done in order to understand what I need to modify in my code to make it work. By writing this short analysis and providing some links to read upon I hope to save someone else from spending a few days to come up with the answer to his problem.
Again I encourage anyone to try implementing RRD's is a very powerful tool to graphically view your results and store the data up to 3 years.
Another update that I think is useful to some people maybe. Instead of following all this process by adding and removing code in order to make the rrd file working.
After modifications and experimentation I found another solution.
use strict;
use RRD::Simple;
use RRDs;
my $rrd = RRD::Simple->new(
file => "myfile.rrd",
rrdtool => "/usr/local/rrdtool-1.2.11/bin/rrdtool", #optional
tmpdir => "/var/tmp", #optional
cf => [ qw(AVERAGE MAX) ], #optional
default_dstype => "COUNTER", #optional
on_missing_ds => "add", #optional
RRDs::tune("myfile.rrd", "-i", "Source_Name:0") #optional -i or --minimum
RRDs::tune("myfile.rrd", "-a", "Source_Name:200") #optional -a or --maximum
);
There are several optional values that someone can use, but I recommend to use all of them so you can take full control of the program.
I am using:
default_dstype => "COUNTER", #optional
Because by default RRD's will set GAUGE as Data Source (DS). By setting the DS to COUNTER the user can set the minimum and maximum values. Short examples can be found here also RRD::Simple::Examples.
I would like to add an SVG bar chart into my web application.
I have to use Catalyst Framework and Template::Toolkit view.
While searching cpan, I have found this module.
I followed the example instructions in the above web-page in order to create a simple graph.
Unfortunately, no chart is rendered in my application.
Firstly I created the view class
./script/myapp_create.pl view Chart SVG::TT::Graph
and added this code inside it
package myapp::View::Chart;
use Moose;
use namespace::autoclean;
use SVG::TT::Graph::BarHorizontal;
my #fields = qw(Jan Feb Mar);
my #data_sales_02 = qw(12 45 21);
my $graph = SVG::TT::Graph::BarHorizontal->new({
'height' => '500',
'width' => '300',
'fields' => \#fields,
});
$graph->add_data({
'data' => \#data_sales_02,
'title' => 'Sales 2002',
});
print "Content-type: image/svg+xml\n\n";
print $graph->burn();
Then I set the chart preferences in my config
<View::Chart>
format png
<chart_conf>
style_sheet /home/john/myapp/root/static/css/style2.css
show_graph_title 1
</chart_conf>
</View::Chart>
Finally I created the below subroutine in my controller
sub getchart :Local :Args(0){
my ( $self, $c ) = #_;
$c->stash->{chart_title} = 'Sales data'; # optional
$c->stash->{chart_type} = 'BarHorizontal'; # or Pie/Line/BarHorizontal
$c->stash->{chart_conf} = {
height => 400,
width => 600
};
$c->stash->{chart_fields} = [ qw(Jan Feb March) ];
$c->stash->{chart_data} = [ 12, 45, 21];
$c->forward($c->view('Chart'));
}
Obviously I am missing something fundamental but I am inexperienced with Catalyst. Any help is highly appreciated. Thanks
Your are printing your graph results to STDOUT. Perhaps this is ending up in your server logs or somewhere else, but if you want Catalyst to send something to a client you have to set the body of your server response. The message body is accessible through the Catalyst context.
There is already some sample code on how to print graphs using a Catalyst::View in the fabulous Catalyst Advent Calendar. At the end of the view's process subroutine you can see how to set the response body.
You could use this sample code and just replace the graph generator with some SVG creation module of your choice.
I'm trying to do my first rrd graph through Perl.
I have tried RRD::Simple and rrds and just can't get either one to work.
Here's what I have so far:
use strict;
use RRD::Simple ();
# Create an interface object
my $rrd = RRD::Simple->new( file => "server.rrd" );
# Put some arbitary data values in the RRD file for the same
# 3 data sources called bytesIn, bytesOut and faultsPerSec.
$rrd->create(
EqSearch => "DERIVE",
MfSearch => "DERIVE",
EQCostBasis => "DERIVE",
MFCostBasis => "DERIVE"
);
$rrd->update(
EqSearch => 2,
MfSearch => 3,
EQCostBasis => 10,
MFCostBasis => 15
);
# Generate graphs:
# /var/tmp/myfile-daily.png, /var/tmp/myfile-weekly.png
# /var/tmp/myfile-monthly.png, /var/tmp/myfile-annual.png
my %rtn = $rrd->graph(
destination => "/Users/cmuench/Documents/Code/perl",
title => "Server A",
vertical_label => "",
interlaced => "",
periods => [qw(hour)]
);
The output is:
graph http://www.mediafire.com/imgbnc.php/a39e2bd662adefa823dca66351db637c5g.jpg
From your above script, the main issue is that you don't have enough data to show in graphs. you can see the data in your rrd using 'rrdtool fetch`.
If you can use bash instead of perl. Look at this "Round Trip and Packet Loss stats with rrdtool"
If you still want to use perl module RRD::Simple, please look at the examples provided with this module i.e. RRD::Simple::Examples Or provide more details about the problem you are facing.