为什么Excel :: Writer :: XLSX中条形图的灯丝不起作用?

时间:2012-09-12 08:41:29

标签: perl xlsx spreadsheet-excel-writer

我创建了一个包含堆积条形图的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 },
);

我使用Excel::Writer::XLSX

的0.5版本

感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

所以,把我相当冗长的评论变成答案。

Excel :: Writer :: XLSX中似乎缺少某些内容。

如果在Excel的图表属性窗口中查看XLSX文件,您会注意到填充颜色为“蓝色”,但边框设置为“无”。这很好,但你没有注意到它,因为你看不到边框丢失或者它与填充颜色相同。

无论如何,填充似乎不起作用。我检查了Excel :: Writer :: XLSX生成的XLSX存档中的chart.xml,并将其与我在Excel中将其更改为“no fill”并保存的地方进行了比较。 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' },
);

当然,这只是一个快速而肮脏的解决方案。我建议为该模块编写一个错误报告,并将此问题/答案作为作者的参考。

答案 1 :(得分:0)

正如@simbabque所说,这是一个错误。

我已经在Github(commit f4e4191e)的主分支上修复了它。

计划在0.51发布,可能会在接下来的两周内发布。

更新:在Excel :: Writer :: XLSX版本0.51中修复。