Excel-PowerPivot-Utils

 view release on metacpan or  search on metacpan

t/02_chinook.t  view on Meta::CPAN

use utf8;
use strict;
use warnings;
use Win32::OLE      qw/CP_UTF8/;
use YAML            qw/LoadFile/;
use Test::More;
use Excel::PowerPivot::Utils;
use Excel::ValueWriter::XLSX;
use LWP::UserAgent;
use DBI;
use Cwd;


#======================================================================
# GLOBALS
#======================================================================

# VBA constants
use constant {

  # https://learn.microsoft.com/en-us/office/vba/api/excel.xlpivotfieldorientation
  xlColumnField => 2,
  xlDataField 	=> 4,
  xlHidden 	=> 0,
  xlPageField 	=> 3,
  xlRowField 	=> 1,

  # https://learn.microsoft.com/en-us/office/vba/api/excel.xlpivottablesourcetype
  xlExternal    => 2,
};

# url and file names
my $db_URL  = "https://raw.githubusercontent.com/lerocha/chinook-database/master/"
            . "ChinookDatabase/DataSources/Chinook_Sqlite.sqlite";
my $db_file = "chinook.sqlite";
my $xl_file = "chinook.xlsx";

# Excel formula for testing the cube result.
# Can't add it through VBA because it would need to be expressed in
# localized language (e.g. 'VALEURCUBE' for a french version of
# Excel). So the trick is to include the formula directly in the XLSX
# file through Excel::ValueWriter::XLSX, before adding the pivot through VBA.
my $formula = 'CUBEVALUE("ThisWorkbookDataModel", '
            .            '"[Measures].[Invoice Lines Percentage Sales]", '
            .            '"[Genre].[Name].[Classical]", '
            .            '"[Customer].[Country].[Austria]")';


#======================================================================
# SETTING UP
#======================================================================

note "downloading $db_URL";
my $ua       = LWP::UserAgent->new(timeout => 5);
my $response = $ua->mirror($db_URL, $db_file);
$response->is_success
  or note "could not download Chinook sqlite database: ", $response->status_line;

SKIP : {
  skip "no sqlite database" if ! -f $db_file;

  note "connecting to the sqlite database";
  my $dbh    = DBI->connect("dbi:SQLite:dbname=$db_file","","", {sqlite_unicode => 1});

  note "generating Excel file $xl_file";
  my $writer = Excel::ValueWriter::XLSX->new();
  $writer->add_sheet(ComputedPivot => (undef) =>  [["=$formula"]]);
  $writer->add_sheets_from_database($dbh);
  $writer->save_as($xl_file);

  # connect to the generated file. Need to have an active Excel, because Pivot operations don't work
  # if we go through Win32::OLE->GetObject() -- don't know why :-(
  my $fullpath_xl_file = (getcwd . "/$xl_file") =~ tr[/][\\]r;
  my $xl  = Win32::OLE->GetActiveObject("Excel.Application")
    or skip "can't connect to an active Excel instance";
  my $workbook = $xl->Workbooks->Open($fullpath_xl_file)
    or skip "cannot open OLE connection to Excel file $fullpath_xl_file";

  # load Power Query and Power Pivot settings
  my $ppu = Excel::PowerPivot::Utils->new(workbook => $workbook);
  my $model_instructions = LoadFile *DATA;
  $ppu->inject_whole_model($model_instructions);

  # create a Pivot Table (percentage of sales per genre, for each customer country)
  my $pcache = $workbook->PivotCaches->Create(xlExternal,
                                              $workbook->Connections("ThisWorkbookDataModel"));
  my $ptable = $pcache->CreatePivotTable("ComputedPivot!R5C1",
                                         'Sales_by_genre_and_country');
  $ptable->CubeFields("[Measures].[Invoice Lines Percentage Sales]")->{Orientation} = xlDataField;
  $ptable->CubeFields("[Genre].[Name]")                             ->{Orientation} = xlColumnField;
  $ptable->CubeFields("[Customer].[Country]")                       ->{Orientation} = xlRowField;

  #======================================================================
  # TESTS
  #======================================================================

  sleep 3; # give time to Excel to recompute the formula
  my $cell = $workbook->Sheets("ComputedPivot")->Range("A1");
  my $val  = $cell->Value;
  ok $val > 0.04 && $val < 0.05, "Pivot correctly computed percentage of sales of Classical in Austria ($val)";

  # cleanup
  $workbook->Close(1); # 1 = true value for 'SaveChanges'
}

done_testing;



__DATA__
#======================================================================
QUERIES :
#======================================================================


  #======================================================================
  - Name        : Album
  #======================================================================
    Description : 
    Formula     : |-
      let
          Album_Table = Excel.CurrentWorkbook(){[Name="Album"]}[Content],
          #"Modified type" = Table.TransformColumnTypes(Album_Table,{
              {"AlbumId", Int64.Type},
              {"Title", type text},
              {"ArtistId", Int64.Type}})
      in
          #"Modified type"

  #======================================================================
  - Name        : Artist
  #======================================================================
    Description : 
    Formula     : |-
      let
          Artist_Table = Excel.CurrentWorkbook(){[Name="Artist"]}[Content],
          #"Modified type" = Table.TransformColumnTypes(Artist_Table,{
              {"ArtistId", Int64.Type},
              {"Name", type text}})
      in
          #"Modified type"

  #======================================================================
  - Name        : Customer
  #======================================================================
    Description : 
    Formula     : |-
      let
          Customer_Table = Excel.CurrentWorkbook(){[Name="Customer"]}[Content],
          #"Modified type" = Table.TransformColumnTypes(Customer_Table,{
              {"CustomerId", Int64.Type},
              {"FirstName", type text},
              {"LastName", type text},
              {"Company", type text},
              {"Address", type text},
              {"City", type text},
              {"State", type text},



( run in 2.272 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )