Excel :: Writer :: XLSX Ошибка нечитаемого содержимого - PullRequest
0 голосов
/ 17 сентября 2018

Я только начал использовать Perl, и я использую Excel::Writer::XLSX запросить базу данных DB2 и экспортировать данные в файл .xlsx. Данные содержат около 250 тыс. Строк.

Сценарий работает нормально, но когда я пытаюсь открыть файл Excel, он выдает ошибку и просит восстановить файл. При восстановлении некоторые данные заменяются на inf.

Error dialog saying

Ниже приведен фрагмент моего кода.

while ( my $sqlStatement = ) {

    $mSQL = $dbh->prepare( $sqlStatement )
            or die "Can't prepare $sqlStatement";
    $mSQL->execute()
            or die "Can't execute $sqlStatement";
}

my $workbook = Excel::Writer::XLSX->new( $ARGV[2] );
$workbook->set_tempdir( '/tempDir/' );
$workbook->set_optimization();

my $worksheet = $workbook->add_worksheet();
$worksheet->keep_leading_zeros();

my $row    = 0;
my $column = 0;

my @emptyRow = ();

$worksheet->write_row( $row++, $column, [ @{ $mSQL->{NAME_uc} } ] );
$worksheet->write_row( $row++, $column, [ @emptyRow ] );

while ( my @Row = $mSQL->fetchrow_array ) {
    $worksheet->write_row( $row++, $column, [ @Row ] );    #, $cellFormat);
    $count++;
}

$workbook->close();

Может кто-нибудь, пожалуйста, посоветовать мне по этому вопросу?

1 Ответ

0 голосов
/ 08 октября 2018

Наконец-то я понял (спасибо Джону Макнамаре). Это было решено добавлением обработчика записи, который использует регулярные выражения, чтобы проверить, конвертируется ли определенный токен в «inf», и, если это так, вызывает подпрограмму write_string вместо write_row. Ниже приведен код.

#!/usr/bin/perl

use strict;
use warnings;
use Excel::Writer::XLSX;


my $workbook  = Excel::Writer::XLSX->new( 'write_handler5.xlsx' );
my $worksheet = $workbook->add_worksheet();


# Add a handler to match any numbers in order to check for and handle
# infinity.
$worksheet->add_write_handler( qr[\d], \&write_with_infinity );


# The following function is used by write() to pre-process any the data when a
# match is found. If it finds something that looks like a number but evaluates
# to infinity it write it as a string.
sub write_with_infinity {

    my $worksheet = shift;
    my @args      = @_;
    my $token     = $args[2];

    # Check if token looks like a number, in the same way as write().
    if ( $token =~ /^([+-]?)(?=[0-9]|\.[0-9])[0-9]*(\.[0-9]*)?([Ee]([+-]?[0-9]+))?$/ ) {

    # Check for infinity.
    $token = $token + 0;

    if ($token =~ /inf/) {

        # Write the value as a string instead of a number.
        return $worksheet->write_string( @args );
    }
    }

    # Reject the match and return control to write()
    return undef;
}
...