@artem78

Почему пропадает текст при склейке Excel файлов в Perl?

Пишу небольшую программку на Perl для объединения xlsx-файлов. Открываю объединённый файл и вижу что текст исчез остались только цифры. Возможно дело в неправильной кодировке, но не могу понять из какой в какую нужно переводить.

sub processButton_Click {
	my $target_file_name = Win32::GUI::GetSaveFileName(
		-title  => 'Сохранить файл',
        -filter => ["Excel (*.xslx)" => "*.xlsx"]
	);
	return unless $target_file_name;
	
	
	$mainWindow->statusLabel->Text('');
	$mainWindow->addButton->Enable(0);
	$mainWindow->removeButton->Enable(0);
	$mainWindow->processButton->Enable(0);
	my $target_workbook = Excel::Writer::XLSX->new("$target_file_name.xlsx");
	my $warns = '';
	my $converter = Text::Iconv->new("utf-8", "windows-1251");
	
	my @source_files = ();
	my $n = $mainWindow->fileList->GetCount();
	foreach my $idx (0 .. $n-1) {
		push(@source_files, $mainWindow->fileList->GetText($idx));
	}

	
	my $thread = threads->create(sub {
		foreach my $i (keys @source_files) {
			$mainWindow->statusLabel->Text("Обработка " . ($i + 1) . " из $n ...");
			my $source_file = $source_files[$i];
			my $reader = Excel::Reader::XLSX->new();
			my $source_workbook = $reader->read_file($source_file);
			if (!defined $source_workbook) {
				$warns .= "Невозможно прочитать $source_file\n";
				next;
			}
			
			$source_file =~ m/^.*(?:\\|\/)(.*?).[a-zA-Z0-9]+$/;
			my $target_worksheet_name = decode('windows-1251', $1);
			my $target_worksheet = $target_workbook->add_worksheet($target_worksheet_name);
			
			my ($source_worksheet) = $source_workbook->worksheets();
		 
			while (my $row = $source_worksheet->next_row()) {
				while (my $cell = $row->next_cell()) {
					my $value = $cell->value();
					$target_worksheet->write($cell->row(), $cell->col(), $value);
				}
			}
		}
		
		$mainWindow->statusLabel->Text('Выполнено');
		$mainWindow->addButton->Enable(1);
		$mainWindow->removeButton->Enable(1);
		$mainWindow->processButton->Enable(1);
		Win32::GUI::MessageBox(0, $warns, '', MB_ICONWARNING()) if $warns;
		
		$target_workbook->close();
	});

}
  • Вопрос задан
  • 2383 просмотра
Пригласить эксперта
Ответы на вопрос 2
@noize
1. Не используйте threads, они deprecated. Если нужно в несколько потоков обрабатывать, делайте лучше через fork
2. Навтыкайте везде print/say, например, после строки
$source_file =~ m/^.*(?:\\|\/)(.*?).[a-zA-Z0-9]+$/;
поставьте print $1 . "\n"; чтобы убедиться, что регулярка верна, ну и дальше по коду так же.
Ответ написан
@gangabass
Возможно дело в Excel::Reader::XLSX. Мой код работает:
use Excel::Writer::XLSX;
use Spreadsheet::ParseXLSX;
use threads;
use feature qw(say);
use Encode qw(decode);

my $target_workbook = Excel::Writer::XLSX->new("Result.xlsx");

#Обрабатываю два файла "Sample_Сентябрь_2014.xlsx" и "Sample_Октябрь_2014.xlsx")
my @source_files = glob("Sample_*.xlsx");


my $thread = threads->create(
    sub {
        foreach my $source_file (@source_files) {

            my $reader          = Spreadsheet::ParseXLSX->new();
            my $source_workbook = $reader->parse($source_file);

            my ($target_worksheet_name) = $source_file =~ m/Sample_(.+)\.xlsx$/;

            $target_worksheet_name =
              decode( 'windows-1251', $target_worksheet_name );
            my $target_worksheet =
              $target_workbook->add_worksheet($target_worksheet_name);

            my ($worksheet) = $source_workbook->worksheets();

            my ( $row_min, $row_max ) = $worksheet->row_range();
            my ( $col_min, $col_max ) = $worksheet->col_range();

            foreach my $row ( $row_min .. $row_max ) {

                foreach my $col ( $col_min .. $col_max ) {

                    my $cell = $worksheet->get_cell( $row, $col );
                    my $value = $cell->value();
                    $target_worksheet->write( $row, $col, $value );
                }
            }
        }

        $target_workbook->close();
        exit;
    }
);

$thread->join();
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы