Почему заполнение гистограммы в Excel::Writer::XLSX не работает?

Я создаю таблицу Excel, включая гистограмму с накоплением. Теперь я хочу, чтобы в первом баре не было цвета, но он все еще синий. Код выглядит так:

$chart->add_series(
    categories    => [ 'Sheet1', 1, $counter, 0, 0 ],
    values        => [ 'Sheet1', 1, $counter, 3, 3 ],
    name          => 'Waiting_time',
    fill          => { none => 1 },
    border        => { none => 1 },
);

Я использую версию 0.5 Excel::Writer::XLSX

Спасибо за вашу помощь.

2 ответа

Итак, чтобы превратить мой довольно длинный комментарий в ответ.

Кажется, что-то не хватает в Excel::Writer::XLSX.

Если вы посмотрите на свой файл XLSX в окне свойств диаграммы Excel, то заметите, что цвет заливки "синий", но для границы установлено значение "нет". Это замечательно, но вы этого не замечаете, потому что не видите, что граница отсутствует или имеет тот же цвет, что и заливка.

Во всяком случае, заполнение, кажется, не работает. Я проверил файл chart.xml внутри архива XLSX, созданного в Excel:: Writer:: XLSX, и сравнил его с тем, где я изменил его в "без заполнения" в Excel и сохранил. Excel создает много накладных расходов, но все сводится к следующему:

<!-- Perl -->
<c:spPr>
  <a:solidFill></a:solidFill>
  <a:ln>
    <a:noFill />
  </a:ln>
</c:spPr>

<!-- after Excel -->
<c:spPr>
  <a:noFill/>
  <a:ln>
    <a:noFill/>
  </a:ln>
</c:spPr>

Мы можем ясно видеть, что должно быть noFill элемент.

Теперь, если мы посмотрим на код в Excel:: Writer:: XLSX:: Chart, есть метод с именем _write_sp_pr, Это делает диаграмму непонятной. Он вызывает два метода по очереди, один для строк и один для заливок.

# Write the a:solidFill element for solid charts such as pie and bar.
if ( $series->{_fill}->{_defined} ) {
    $self->_write_a_solid_fill( $series->{_fill} );
}

# Write the a:ln element.
if ( $series->{_line}->{_defined} ) {
    $self->_write_a_ln( $series->{_line} );
}

Второй, _write_a_lnзаботится о none => 1:

sub _write_a_ln {
    # [...]

    # Write the line fill.
    if ( $line->{none} ) {

        # Write the a:noFill element.
        $self->_write_a_no_fill();
    }

    # [...]
}

Это замечательно. Так что нет линии. Но где проверить цвет заливки?

sub _write_a_solid_fill {

    my $self = shift;
    my $line = shift;

    $self->{_writer}->startTag( 'a:solidFill' );

    if ( $line->{color} ) {

        my $color = $self->_get_color( $line->{color} );

        # Write the a:srgbClr element.
        $self->_write_a_srgb_clr( $color );
    }

    $self->{_writer}->endTag( 'a:solidFill' );
}

Оказывается, нет. Если цвет не установлен, он опускается. Но это заставляет Excel использовать цвет по умолчанию, который должен быть синим.


Чтобы это исправить, попробуйте следующий monkeypatch. Добавьте этот материал в начало вашей программы, которая создает файл XLSX с диаграммой. Это позаботится о незаполнении. Это полный саб _write_sp_pr из исходного кода модуля с добавлением немного дополнительной логики.

use Excel::Writer::XLSX;
{
  no warnings 'redefine';
  sub Excel::Writer::XLSX::Chart::_write_sp_pr {

      my $self   = shift;
      my $series = shift;

      if ( !$series->{_line}->{_defined} and !$series->{_fill}->{_defined} ) {
          return;
      }

      $self->{_writer}->startTag( 'c:spPr' );

      # Write the a:solidFill element for solid charts such as pie and bar.
      if ( $series->{_fill}->{_defined} ) {
          # Check if a noFill element is needed
          if ( $series->{_fill}->{none} ) {
              # Write the a:noFill element.
              $self->_write_a_no_fill();
          } else {
              # Write the line fill.
              $self->_write_a_solid_fill( $series->{_fill} );
          }
      }

      # Write the a:ln element.
      if ( $series->{_line}->{_defined} ) {
          $self->_write_a_ln( $series->{_line} );
      }

      $self->{_writer}->endTag( 'c:spPr' );
  }
}

Вот еще немного кода, чтобы попробовать его очень быстро:

use strict; use warnings;
#### put above code here 

# Create a new Excel workbook
my $workbook = Excel::Writer::XLSX->new( 'perl.xlsx' );

# Add a worksheet
my $worksheet = $workbook->add_worksheet();
foreach my $row (0 .. 9) {
  foreach my $col (0 .. 4) {
    $worksheet->write($row, $col, $row+1);
  }
}

my $chart = $workbook->add_chart( type => 'bar' );
$chart->add_series(
    categories    => [ 'Sheet1', 1, 5, 0, 0 ],
    values        => [ 'Sheet1', 1, 5, 3, 3 ],
    name          => 'Waiting_time',
    fill          => { none => 1 },
    border        => { color => 'red' },
);

Конечно, это просто быстрое и грязное решение. Я предлагаю написать отчет об ошибке для модуля и использовать этот вопрос / ответ в качестве справочного материала для автора.

Как говорит @simbabque, это ошибка.

Я исправил это в основной ветке на Github ( commit f4e4191e).

Он запланирован на выпуск 0.51, который, вероятно, будет в ближайшие 2 недели.

Обновление: исправлено в версии 0.51 Excel::Writer::XLSX.

Другие вопросы по тегам