EnzoXenon has asked for the wisdom of the Perl Monks concerning the following question:

In PowerPoint.pm extension to Win32::OLE I added a routine to create a line in a PowerPoint - like this it works!
sub add_line { my ($self, $options) = @_; return unless $self->slide; $options = {} unless ref $options eq 'HASH'; my $new_line = $self->slide->Shapes->AddLine($options->{x1}, $option +s->{y1}, $options->{x2}, $options->{y2}); $new_line->{Line}{ForeColor}{RGB}=RGB($options->{forecolor}) if(defi +ned $options->{forecolor}); $new_line->{Line}{Weight}=$options->{weight} if(defined $options->{w +eight}); $new_line->{Line}{Pattern}=$options->{pattern} if(defined $options-> +{pattern}); return $new_line; }
Now I'm trying to add a routine to make a polyline ... (so I can draw arbitrary and not just mso Shapes) and I coded it like this:
sub add_polyline { my ($self, $options) = @_; return unless $self->slide; $options = {} unless ref $options eq 'HASH'; my $new_poly=$self->slide->Shapes->AddPolyline($options->{points}); $new_poly->{Line}{ForeColor}{RGB}=RGB($options->{forecolor}) if(defi +ned $options->{forecolor}); $new_poly->{Line}{Weight}=$options->{weight} if(defined $options->{w +eight}); $new_poly->{Line}{Pattern}=$options->{pattern} if(defined $options-> +{pattern}); if(defined $options->{fillcolor}) { $new_poly->{Fill}{ForeColor}{RGB}=RGB($options->{fillcolor}); } else { $new_poly->{Fill}{Transparency}=1; } return $new_poly; }
Which does not work. The argument needed by the microsoft routine AddPolyline is something called a "SafeArrayOfPoints" in the docos.

https://documentation.help/Microsoft-PowerPoint-Visual-Basic/ppmthAddPolyline1.htm

I've tried an array, a two-dimensional array, and array reference ... nothing works.

Can anyone help?

Replies are listed 'Best First'.
Re: PowerPoint.pm extension for AddPolyline not working
by Corion (Patriarch) on Jun 14, 2023 at 07:33 UTC

    According to the Microsoft documentation for AddPolyline, the method takes a Variant datatype. Without testing, you should be able to create a (2-dimensional) Variant that contains an array (of integers) like this:

    use Win32::OLE; use Win32::OLE::Variant; my $pointcount = 4; # 4 points my $point_dimensions = 2; # The arrayrefs mean we use 1-based indices, like the VBA examples do: # my $pointlist = Variant(VT_ARRAY | VT_R4 , [1,$pointcount], [1,$poin +t_dimensions]); # Alternatively, use 0-based indices, like Perl does: my $pointlist = Variant(VT_ARRAY | VT_R4 , $pointcount, $point_dimensi +ons); $pointlist->Put( 0,0, 25 ); $pointlist->Put( 0,1, 100 ); ... $slide->Shapes->AddPolyline($pointlist);

    The MS documentation suggests that the SafeArryOfPoints should be a 2-dimensional array.

      Corion ... thank you very much!

      Here's what I put into the PowerPoint module per your guidance on Win32::OLE::Variant (which I looked up on CPAN afterward ... because I should learn how to read)

      # Get the points my @points=@{ $options->{points} }; # Create the Win32::OLE::Variant my $pointlist = Win32::OLE::Variant->new(VT_ARRAY | VT_R4 , 4, 2); # Convert points to Win32::OLE::Variant for my $index (0 .. 3) { # Add x $pointlist->Put( $index, 0, shift(@points) ); # Add y $pointlist->Put( $index, 1, shift(@points) ); } my $new_poly=$self->slide->Shapes->AddPolyline($pointlist);
      So I could make the call into the function simple ...
      # Add filled Triangle $PPT->add_polyline( {'points' => [$pptpoints[0], $pptpoints[1 +], $pptpoints[2], $pptpoints[3], $pptpoints[4], $pptpoints[5], $pptpo +ints[0], $pptpoints[1]], 'fillcolor' => &convert2RGBvalues($fill), 'weight' => $weight/px2pt, 'forecolor' => &convert2RGBvalues($color) } +);
      Meaning the user will only have to define a list of three coordinate pairs in perl to make a triangle in PowerPoint.

      EXCELLENT!

Re: PowerPoint.pm extension for AddPolyline not working
by EnzoXenon (Acolyte) on Jun 14, 2023 at 02:34 UTC
    And the call to use add_poly is like this ...
    # Add filled Triangle $PPT->add_polyline( {'points' => [[$pptpoints[0], $pptpoints[ +1]], [$pptpoints[2], $pptpoints[3]], [$pptpoints[4], $pptpoints[5]], +[$pptpoints[0], $pptpoints[1]]], 'fillcolor' => &convert2RGBvalues($fill), 'weight' => $weight/px2pt, 'forecolor' => &convert2RGBvalues($color) } +);
    Although, as I've said I've tried multiple variations of the list for 'points'

    The net result is that my $new_poly never gets set and the next line that uses $new_poly says "Use of uninitialized value $new_poly" yet no errors are thrown.