http://www.perlmonks.org?node_id=743574
Category: Utillity Scripts
Author/Contact Info /msg Corion
Description:

This script is a raw utility that I use to merge "information" and "data" sheets from different Excel workbooks. The basic syntax is as follows:

xlsmerge -s -o results-%Y%m%d.xls info.xls:Information query_results.x +ls:Sheet1

The above command line will create results-20091302.xls containing a worksheet "Information" and one worksheet "Sheet1" from the respective Excel files. There is no renaming functionality and duplicate sheet names are fatal.

#!/usr/bin/perl -w
use strict;
use Spreadsheet::ParseExcel;
use Spreadsheet::WriteExcel;
use File::Glob qw(bsd_glob);
use Getopt::Long;
use POSIX qw(strftime);

GetOptions(
    'output|o=s' => \my $outfile,
    'strftime|t' => \my $do_strftime,
) or die;

if ($do_strftime) {
    $outfile = strftime $outfile, localtime;
};

my $output = Spreadsheet::WriteExcel->new($outfile)
    or die "Couldn't create '$outfile': $!";

for (@ARGV) {
    my ($filename,$sheetname,$targetname);
    my @files;
    if (m!^(.*\.xls):(.*?)(?::([\w ]+))$!) {
        ($filename,$sheetname,$targetname) = ($1,qr($2),$3);
        warn $filename;
        if ($do_strftime) {
            $filename = strftime $filename, localtime;
        };
        @files = glob $filename;
    } else {
        ($filename,$sheetname,$targetname) = ($_,qr(.*),undef);
        if ($do_strftime) {
            $filename = strftime $filename, localtime;
        };
        push @files, glob $filename;
    };

    for my $f (@files) {
        my $excel = Spreadsheet::ParseExcel::Workbook->Parse($f);
        foreach my $sheet (@{$excel->{Worksheet}}) {
            if ($sheet->{Name} !~ /$sheetname/) {
                warn "Skipping '" . $sheet->{Name} . "' (/$sheetname/)
+";
                next;
            };
            $targetname ||= $sheet->{Name};
            #warn sprintf "Copying %s to %s\n", $sheet->{Name}, $targe
+tname;

            my $s = $output->add_worksheet($targetname);
            $sheet->{MaxRow} ||= $sheet->{MinRow};
            foreach my $row ($sheet->{MinRow} .. $sheet->{MaxRow}) {
                my @rowdata = map {
                    $sheet->{Cells}->[$row]->[$_]->{Val};
                } $sheet->{MinCol} ..  $sheet->{MaxCol};
                $s->write($row,0,\@rowdata);
            }
        }
    };
};

$output->close;
  • Comment on xlsmerge - Merge worksheets from different Excel files into one Workbook
  • Download Code
Replies are listed 'Best First'.
Re: xlsmerge - Merge worksheets from different Excel files into one Workbook
by ambrus (Abbot) on Jun 15, 2010 at 13:03 UTC

    You know, if you open two workbooks in Excel and right-click on the sheet selection tab, you get a shortcut menu with a "Move/copy sheet..." entry that lets you copy sheets even among workbooks. What advantage does this script have over that method?

      The advantage of all my scripts. I don't have to do menial tasks manually, like merging boilerplate sheets into other workbooks before mailing them.

Re: xlsmerge - Merge worksheets from different Excel files into one Workbook
by Anonymous Monk on Nov 19, 2013 at 20:29 UTC
    My formulas are not coming over with the data, it is just showing 0 instead. Any ideas?

      The script only copies values, not formulas. For copying formulas, you'll have to look at how Spreadsheet::ParseExcel offers the formulas, and then copy those instead of the values.

A reply falls below the community's threshold of quality. You may see it by logging in.