Perl vCard.pm how do I compute inputs? - perl

The documentation for vCard shows it wants:
addresses()
Accepts/returns an arrayref that looks like:
[
{ type => ['work'], street => 'Main St', preferred => 0 },
{ type => ['home'],
pobox => 1234,
extended => 'asdf',
street => 'Army St',
city => 'Desert Base',
region => '',
post_code => '',
country => 'USA',
preferred => 1,
},
]
I must generate this call from a CSV file. I can extract the data, but cannot figure out how to pass it to $vcard->addresses.
This fails:
if (keys %addrwork > 0 )
{
$addrwork{'type'} = ['work'];
push #arraytmp, %addrwork;
}
# did we get any part of a home or work address?
if ( $#arraytmp >= 0 ) {
$vcard->addresses( #arraytmp );
Fails with:
Can't use string ("type") as an ARRAY ref while "strict refs" in use at /usr/local/share/perl/5.22.1/vCard.pm line 254, <FILE> line 2.

Accepts/returns an arrayref that looks like:
You're passing an array, not an arrayref. Fix it:
$vcard->addresses( \#arraytmp );

Related

Rearrange data in a PDF file

I am using Perl to generate a PDF file with the
PDF::API2 module.
I am having difficulty writing data to the file in the required format.
Currently this is how it appears in the PDF file.
Here's my script
my %data = (
'1' => {
'SEQUENCE' => '1',
'NAME' => 'John',
'ADDR1' => 'Road 1',
'GRADE' => '5'
},
'2' => {
'SEQUENCE' => '2',
'NAME' => 'Smith',
'ADDR1' => 'Road 2',
'GRADE' => '6'
}
);
...
...
my #rows = qw( NAME ADDR1 GRADE );
for my $id (sort keys %data){
push #tbl, [ #{$data{$id}}{#rows} ];
($name, $addr, $grade) = ($data{$id}{'NAME'}, $data{$id}{'ADDR1'}, $data{$id}{'GRADE'});
}
...
...
my $pdftable = new PDF::Table;
$pdftable->table(
$pdf,
$page,
\#tbl,
x => 50,
w => 400,
start_y => 630,
start_h => 630,
next_y => 630,
next_h => 630,
padding => 5,
border => 1,
padding_right => 10,
);
$pdf->saveas();
But I want it to to appear like this:
I know I have to make a modification to #tbl data, but how?
The PDF::Table table function takes an "array or arrays" as its third argument. You currently have it strucutred like:
my #tbl = ( [$name,$addr,$grade], [...] )
Each nested array (what's inside the [] brackets) is a new row of the table, and the elements to that array are the cells of that row. So instead, you want it structured:
my #tbl = ( ['NAME',$name], ['ADDR1',$addr], ['GRADE',$grade], [...] )
To construct it using your %data structure:
for my $id (sort keys %data) {
push #tbl, [$_, $data{$id}->{$_}] for qw/NAME ADDR1 GRADE/;
push #tbl, [qw/- -/]; # to add a blank row as a separator
}

Inserting one hash into another using Perl

I've tried many different versions of using push and splice, but can't seem to combine two hashes as needed. Trying to insert the second hash into the first inside the 'Item' array:
(
ItemData => { Item => { ItemNum => 2, PriceList => "25.00", UOM => " " } },
)
(
Alternate => {
Description => "OIL FILTER",
InFile => "Y",
MfgCode => "FRA",
QtyAvailable => 29,
Stocked => "Y",
},
)
And I need to insert the second 'Alternate' hash into the 'Item' array of the first hash for this result:
(
ItemData => {
Item => {
Alternate => {
Description => "OIL FILTER",
InFile => "Y",
MfgCode => "FRA",
QtyAvailable => 29,
Stocked => "Y",
},
ItemNum => 2,
PriceList => "25.00",
UOM => " ",
},
},
)
Can someone suggest how I can accomplish this?
Assuming you have two hash references, this is straight-forward.
my $item = {
'ItemData' => {
'Item' => {
'PriceList' => '25.00',
'UOM' => ' ',
'ItemNum' => '2'
}
}
};
my $alt = {
'Alternate' => {
'MfgCode' => 'FRA',
'Description' => 'OIL FILTER',
'Stocked' => 'Y',
'InFile' => 'Y',
'QtyAvailable' => '29'
}
};
$item->{ItemData}->{Item}->{Alternate} = $alt->{Alternate};
The trick here is not to actually merge $alt into some part of $item, but to only take the specific part you want and put it where you want it. We take the Alternate key from $alt and put it's content into a new Alternate key inside the guts of $item.
Adam Millerchip pointed out in a hence deleted comment that this is not a copy. If you alter any of the keys inside of $alt->{Alternative} after sticking it into $item, the data will be changed inside of $item as well because we are dealing with references.
$item->{ItemData}->{Item}->{Alternate} = $alt->{Alternate};
$alt->{Alternate}->{InFile} = 'foobar';
This will actually also change the value of $item->{ItemData}->{Item}->{Alternate}->{InFile} to foobar as seen below.
$VAR1 = {
'ItemData' => {
'Item' => {
'ItemNum' => '2',
'Alternate' => {
'Stocked' => 'Y',
'MfgCode' => 'FRA',
'InFile' => 'foobar',
'Description' => 'OIL FILTER',
'QtyAvailable' => '29'
},
'UOM' => ' ',
'PriceList' => '25.00'
}
}
};
References are supposed to do that, because they only reference something. That's what's good about them.
To make a real copy, you need to dereference and create a new anonymous hash reference.
# create a new ref
# deref
$item->{ItemData}->{Item}->{Alternate} = { %{ $alt->{Alternate} } };
This will create a shallow copy. The values directly inside of the Alternate key will be copies, but if they contain references, those will not be copied, but referenced.
If you do want to merge larger data structures where more than the content of one key needs to be merged, take a look at Hash::Merge instead.

For each object in array in perl

I am trying to loop through each object in an array in Perl and I think I am making an obvious error.
my #members_array = [
{
id => 1234,
email => 'first#example.com',
}, {
id => 4321,
email => 'second#example.com',
}
];
use Data::Dumper;
for my $member ( #members_array ) {
print Dumper( $member );
}
Expected output for first iteration
{
id => 1234,
email => 'first#example.com',
}
Actual output for first iteration
[{
'email' => 'first#example.com',
'id' => 1234
}, {
'email' => 'second#example.com',
'id' => 4321
}];
How do I loop through these elements in the array? Thanks!
[ ... ] is used to create an array reference; you need to use ( ... ) to create an array :
my #members_array = (
{
id => 1234,
email => 'first#example.com',
}, {
id => 4321,
email => 'second#example.com',
}
);
And then the rest of your code will work just fine.

Unable to supply complex form values using WWW::Mechanize

I have an HTML form that I want to process with the WWW::Mechanize module. It seems that I can't POST an input value that contains a dollar sign $. I get this run time error message:
Can't call method "value" on an undefined value at script.pl line 599
My script looks like this
my $agent = WWW::Mechanize->new( autocheck => 1, ssl_opts => { verify_hostname => 0 }, );
my $formfiller = WWW::Mechanize::FormFiller->new();
$agent->env_proxy();
$agent->get('https://site.com/form.php');
$agent->form_number(1) if $agent->forms and scalar #{$agent->forms};
$agent->form_number(1);
{
local $^W;
$agent->current_form->value('page_contentleft_0$form_D69D9E5239FC412ABB92A81D73F690AD$field_F40A1785D7B3490CBD5E72EDBE6B966D', 'John Doe');
}; #// First NAme
{
local $^W;
$agent->current_form->value('page_contentleft_0$form_D69D9E5239FC412ABB92A81D73F690AD$field_E3316C46A4404C73ACBAE107DF6206D2', 'Bridgeport');
}; #// City
{
local $^W;
$agent->current_form->value('page_contentleft_0$form_D69D9E5239FC412ABB92A81D73F690AD$field_E5747EB507E74DC1937557F9285CB57C', 'CT');
}; #// state
{
local $^W;
$agent->current_form->value('page_contentleft_0$form_D69D9E5239FC412ABB92A81D73F690AD$field_A612569BE44C4BA3AD0AB3FBF8FB0553', '06604');
}; #// Zipcode
$agent->submit(Submit);
As far as I can see the problem is from the parameters to the value method, for instance
page_contentleft_0$form_D69D9E5239FC412ABB92A81D73F690AD$field_A612569BE44C4BA3AD0AB3FBF8FB0553
How can I make Perl pass through the $, or to fix it in another way?
Are you sure you have?
$agent->submit(Submit);
Try this code instead:
$agent->get('https://site.com/form.php');
$agent->submit_form(
with_fields => {
'page_contentleft_0$form_D69D9E5239FC412ABB92A81D73F690AD$field_F40A1785D7B3490CBD5E72EDBE6B966D' => 'John Doe',
'page_contentleft_0$form_D69D9E5239FC412ABB92A81D73F690AD$field_E3316C46A4404C73ACBAE107DF6206D2' => 'Bridgeport',
'page_contentleft_0$form_D69D9E5239FC412ABB92A81D73F690AD$field_E5747EB507E74DC1937557F9285CB57C' => 'CT',
'page_contentleft_0$form_D69D9E5239FC412ABB92A81D73F690AD$field_A612569BE44C4BA3AD0AB3FBF8FB0553' => '06604'},
button => "Submit",);

How do I access certain keys in a Perl nested hash?

I dumped a data structure:
print Dumper($bobo->{'issues'});
and got:
$VAR1 = {
'155' => {
'name' => 'Gender',
'url_name' => 'gender'
}
};
How can I extract 155?
How about if I have:
$VAR1 = {
'155' => {'name' => 'Gender', 'url_name' => 'gender'},
'11' => {'name' => 'Toddler', 'url_name' => 'toddler'},
'30' => {'name' => 'Lolo', 'url_name' => 'lolo'}
};
I want to print one key, i.e. the first or second to see the value of the key?
So, based on the example you posted, the hash looks like this:
$bobo = {
issues => {
155 => {
name => 'Gender',
url_name => 'gender',
},
},
};
'155' is a key in your example code. To extract a key, you would use keys.
my #keys = keys %{$bobo->{issues}};
But to get the value that 155 indexes, you could say:
my $val = $bobo->{issues}{155};
Then $val would contain a hashref that looks like this:
{
name => 'Gender',
url_name => 'gender'
}
Have a look at perldoc perlreftut.
It is a key in the hash referenced by $bobo->{'issues'}. So you would iterate through
keys %{$bobo->{'issues'}}
to find it.