PHPOffice

PHPOffice

Member Since 9 years ago

The Internet

Experience Points
0
follower
Lessons Completed
0
follow
Best Reply Awards
7
repos
Jun
23
9 hours ago
started
started time in 53 minutes ago
started
started time in 1 hour ago
Activity icon
issue

brianlmerritt issue comment PHPOffice/PhpSpreadsheet

brianlmerritt
brianlmerritt

Phpspreadsheet Charts don't work when adding multiple sheets - demo code works fine one worksheet, blank for 2+

This is:

- [x] a bug report
- [ ] a feature request
- [ ] **not** a usage question (ask them on https://stackoverflow.com/questions/tagged/phpspreadsheet or https://gitter.im/PHPOffice/PhpSpreadsheet)

What is the expected behavior?

Creating charts with multiple worksheets should not be different from creating charts with just one worksheet

What is the current behavior?

I can create one or 2 charts happily so long as I stick to the first worksheet, but as soon as I add multiple worksheets the charts written are corrupted or just blank.

What are the steps to reproduce?

Please provide a Minimal, Complete, and Verifiable example of code that exhibits the issue without relying on an external Excel file or a web server:

If you run the code below with $stickToOneSheet set to true, the code runs fine.

There are several options for adding a worksheet and 2 (different?) $writers and none of them produce working charts if there is more than one worksheet.

<?php

require __DIR__ . '/vendor/autoload.php';
use PhpOffice\PhpSpreadsheet\Chart\Chart;
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
use PhpOffice\PhpSpreadsheet\Chart\Legend;
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
use PhpOffice\PhpSpreadsheet\Chart\Title;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;



$stickToOneSheet = true;
$useNewWriterFactory = false;
$cloneNewWorksheet = true; // Only relevant if multiple sheets
$multipleCharts = true;
$title = 'newworksheet';

$spreadsheet = new Spreadsheet();

if ($stickToOneSheet) {
    $worksheet = $spreadsheet->getActiveSheet();

} elseif ($cloneNewWorksheet) {
    $worksheet1 = $spreadsheet->getActiveSheet();
    $worksheet = clone $worksheet1;
    $worksheet->setTitle($title);
    $spreadsheet->addSheet($worksheet,1);
} elseif ($useNewWriterFactory) {

    $worksheet = new Worksheet($spreadsheet, $title);
    $spreadsheet->addSheet($worksheet,1);
} else {
    echo "Sorry, no idea what you want to test";
    die;
}


// Todo generate data in this format
$data = [  // Note this data need to be transposed
    ['Tutor Dashboard Report for someone@example.com'],
    [''],
    ['','Course Minutes','Quiz Minutes','Book Minutes','Other Minutes','Panopto Minutes','Total Minutes', 'Graded Activities', '# Vidoes Watched', '# Watched Completely', 'Quartile Rank'],
    ['Sep20',22,23,65,60,37,256,2,3,2,1],
    ['Oct20',18,39,47,68,38,256,2,3,2,1],
    ['Nov20',12,15,43,67,38,256,4,3,2,3],
    ['Dec20',4,1,154,0,21,256,2,3,2,1],
    ['Jan21',22,15,38,18,10,256,4,4,2,4],
    ['Feb21',18,39,47,68,38,256,2,3,2,1],
    ['Mar21',12,15,43,67,38,256,2,5,2,1],
    ['Apr21',4,1,154,14,21,256,2,1,1,1],
    ['May21',18,39,47,68,38,256,2,3,2,2],
];


$worksheet->fromArray($data);


$num_columns = count($data[2]);
$num_rows = count($data)-3;
echo "\n\nColumns: $num_columns, Rows: $num_rows\n\n";

// Set the Labels for each data series we want to plot
//     Datatype
//     Cell reference for data
//     Format Code
//     Number of datapoints in series
//     Data values
//     Data Marker
//Todo set start values to calculations
$dataSeriesLabels = [
    new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$B$3', null, 1), // Course
    new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$C$3', null, 1), // Quiz
    new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$D$3', null, 1), // Books
    new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$E$3', null, 1), // Other
    new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$F$3', null, 1), // Panopto
];
// Set the X-Axis Labels
//     Datatype
//     Cell reference for data
//     Format Code
//     Number of datapoints in series
//     Data values
//     Data Marker
$xAxisTickValues = [
    //Todo set values to calculations
    new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$A$4:$A$12', null, 4), // Q1 to Q4
];
// Set the Data values for each data series we want to plot
//     Datatype
//     Cell reference for data
//     Format Code
//     Number of datapoints in series
//     Data values
//     Data Marker
//Todo set start and end values to calculations
$dataSeriesValues = [
    new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$B$4:$B$12', null, 4),
    new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$4:$C$12', null, 4),
    new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$D$4:$D$12', null, 4),
    new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$E$4:$E$12', null, 4),
    new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$F$4:$F$12', null, 4),
];

// Build the dataseries
$series = new DataSeries(
    DataSeries::TYPE_BARCHART, // plotType
    DataSeries::GROUPING_STACKED, // plotGrouping
    range(0, count($dataSeriesValues) - 1), // plotOrder
    $dataSeriesLabels, // plotLabel
    $xAxisTickValues, // plotCategory
    $dataSeriesValues        // plotValues
);
// Set additional dataseries parameters
//     Make it a vertical column rather than a horizontal bar graph
$series->setPlotDirection(DataSeries::DIRECTION_COL);

// Set the series in the plot area
$plotArea = new PlotArea(null, [$series]);
// Set the chart legend
$legend = new Legend(Legend::POSITION_RIGHT, null, false);

$title = new Title('Tutor Dashboard - brmerritt@rvc.ac.uk'); // Todo add student email
$yAxisLabel = new Title('Learning Minutes');

// Create the chart
$chart = new Chart(
    'chart1', // name
    $title, // title
    $legend, // legend
    $plotArea, // plotArea
    true, // plotVisibleOnly
    DataSeries::EMPTY_AS_GAP, // displayBlanksAs
    null, // xAxisLabel
    $yAxisLabel  // yAxisLabel
);

// Set the position where the chart should appear in the worksheet
$chart->setTopLeftPosition('A'.($num_rows + 7));
$chart->setBottomRightPosition('M'.($num_rows + 22));

// Add the chart to the worksheet
$worksheet->addChart($chart);

if ($multipleCharts) {


    // OK, try adding another chart!
    $dataSeriesLabels2 = [
        //new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$G$3', null, 1), // Total Minutes - ignore!
        new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$H$3', null, 1), // Graded Activities
        new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$I$3', null, 1), // Videos Watched
        new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$J$3', null, 1), // Watched Completely
        new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$K$3', null, 1), // Quartile Ranking
    ];
    $xAxisTickValues2 = [
        //Todo set values to calculations
        new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$A$4:$A$12', null, 4), // Q1 to Q4
    ];

    //Todo set start and end values to calculations
    $dataSeriesValues2 = [
        new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$H$4:$H$12', null, 4),
        new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$I$4:$I$12', null, 4),
        new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$J$4:$J$12', null, 4),
        new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$K$4:$K$12', null, 4),
        //new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$F$4:$F$12', null, 4),
    ];

    // Build the dataseries
    $series2 = new DataSeries(
        DataSeries::TYPE_BARCHART, // plotType
        DataSeries::GROUPING_CLUSTERED, // plotGrouping
        range(0, count($dataSeriesValues2) - 1), // plotOrder
        $dataSeriesLabels2, // plotLabel
        $xAxisTickValues2, // plotCategory
        $dataSeriesValues2        // plotValues
    );
    // Set additional dataseries parameters
    //     Make it a vertical column rather than a horizontal bar graph
    $series2->setPlotDirection(DataSeries::DIRECTION_COL);

    // Set the series in the plot area
    $plotArea2 = new PlotArea(null, [$series2]);
    // Set the chart legend
    $legend2 = new Legend(Legend::POSITION_RIGHT, null, false);

    $title2 = new Title('Graded Activities, Videos Watched, and Quartile Ranking'); // Todo add student email
    $yAxisLabel2 = new Title('Number of Each');


    $chart2 = new Chart(
        'chart2', // name
        $title2, // title
        $legend2, // legend
        $plotArea2, // plotArea
        true, // plotVisibleOnly
        DataSeries::EMPTY_AS_GAP, // displayBlanksAs
        null, // xAxisLabel
        $yAxisLabel2  // yAxisLabel
    );
    // Set the position where the chart should appear in the worksheet
    $chart2->setTopLeftPosition('A' . ($num_rows + 29));
    $chart2->setBottomRightPosition('M' . ($num_rows + 44));

    // Add the chart to the worksheet
    $worksheet->addChart($chart2);
}

// Save Excel file

$filename = "test_col1_stacked_7.xlsx";
if ($useNewWriterFactory) {
    $writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
} else {
    $writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
}

$writer->setIncludeCharts(true);
$callStartTime = microtime(true);
$writer->save($filename);
return 0;

// add code that show the issue here...

$stickToOneSheet = false; // Change the code above and the charts will not have visible data or be corrupted.

Which versions of PhpSpreadsheet and PHP are affected?

PHP 7.4.12 Phpspreadsheet versions 1.16 and 1.18 Excel version 2105 build 14026...

brianlmerritt
brianlmerritt

Evidently having a dash character in the worksheet name is also an issue. Not going to reopen this issue but if I get time I will debug further and raise a new issue.

pull request

MarkBaker merge to PHPOffice/PhpSpreadsheet

MarkBaker
MarkBaker

Check for existance of cellCollection before we try to use it

Will update these as I go along after we confirm the fix is good in our internal projects.

This is:

- [X ] a bugfix
- [ ] a new feature

Checklist:

Why this change is needed?

MarkBaker
MarkBaker

What problem is this trying to solve? What error does it fix? How can we replicate that error?

If a worksheet exists, then a cell collection should also exist, because it's defined in the sheet's constructor, so it would be better to determine if the worksheet exists.

We need unit tests to prove that this works if it is a fix for some problem

pull request

MarkBaker merge to PHPOffice/PhpSpreadsheet

MarkBaker
MarkBaker

Check for existance of cellCollection before we try to use it

Will update these as I go along after we confirm the fix is good in our internal projects.

This is:

- [X ] a bugfix
- [ ] a new feature

Checklist:

Why this change is needed?

MarkBaker
MarkBaker

What problem is this trying to solve? What error does it fix? How can we replicate that error?

If a worksheet exists, then a cell collection should also exist, because it's defined in the sheet's constructor.

We need unit tests to prove that this works if it is a fix for some problem

pull request

MarkBaker merge to PHPOffice/PhpSpreadsheet

MarkBaker
MarkBaker

Check for existance of cellCollection before we try to use it

Will update these as I go along after we confirm the fix is good in our internal projects.

This is:

- [X ] a bugfix
- [ ] a new feature

Checklist:

Why this change is needed?

MarkBaker
MarkBaker

What problem is this trying to solve? What error does it fix?

If a worksheet exists, then a cell collection should also exist, because it's defined in the sheet's constructor.

We need unit tests to prove that this works if it is a fix for some problem

started
started time in 4 hours ago
started
started time in 5 hours ago
started
started time in 7 hours ago
Activity icon
fork

repost-em forked PHPOffice/PHPExcel

⚡ ARCHIVED
repost-em Updated
fork time in 7 hours ago
Activity icon
fork

repost-em forked PHPOffice/PhpSpreadsheet

⚡ A pure PHP library for reading and writing spreadsheet files
repost-em MIT License Updated
fork time in 7 hours ago
pull request

thunderquiet pull request PHPOffice/PhpSpreadsheet

thunderquiet
thunderquiet

Check for existance of cellCollection before we try to use it

Will update these as I go along after we confirm the fix is good in our internal projects.

This is:

- [X ] a bugfix
- [ ] a new feature

Checklist:

Why this change is needed?

Jun
22
1 day ago
Activity icon
issue

oleibman issue comment PHPOffice/PhpSpreadsheet

oleibman
oleibman

Y2038 Problems?

This is:

- [x] a bug report
- [ ] a feature request
- [ ] **not** a usage question (ask them on https://stackoverflow.com/questions/tagged/phpspreadsheet or https://gitter.im/PHPOffice/PhpSpreadsheet)

What is the expected behavior?

Software should continue to work after epoch change in 2038.

What is the current behavior?

Running on 64-bit Php is probably okay. 32-bit may have problems.

What are the steps to reproduce?

Too early? I think not. YMMV. The analysis below is probably not complete, but it's a start.

PHP itself has some Y2038 exposure (e.g. see https://bugs.php.net/bug.php?id=64992). Dealing with these is clearly out of scope for PhpSpreadsheet.

I think that PhpSpreadsheet is pretty well positioned to avoid problems. However, it does use functions mktime, gmmktime, and strtotime. Those functions will work just fine after the Y2038 transition when 64-bit PHP is used. However, they will fail when 32-bit PHP is used. It is hard to guess if 32-bit PHP will even be a thing when the time comes, but it's best to be prepared. I don't know that it is possible to make 64-bit a requirement, and, even if it is, doing that seems far too drastic. On the other hand, it should be possible to have the unit tests run in a 32-bit region. I don't know how to arrange that. I would suggest that it is probably sufficient to run one 32-bit region rather than a 32-bit version of each supported release of PHP.

Scanning the source code, I find the following use of mktime/gmmktime:

  • samples/templates/SampleSpreadsheet - gmmktime is used to populate one cell with the current date. This is very easily solved by instead using DateTime (which is supported beyond the epoch even on 32-bit systems), and I have a PR which I will be pushing shortly to address this.
  • Worksheet/Autofilter and 3 samples/10_Autofilter*. This is likely to fail before the others, since the tests involve filtering on future dates.
  • Shared/OLE - this looks fairly easy to recode, although research is needed to come up with suitable test cases.

The use of strtotime is more extensive. I haven't researched any of these:

  • Document/Properties
  • Reader/Gnumeric
  • Reader/Ods
  • Reader/Xml
  • Reader/Ods/Properties
  • Reader/Xlsx/Properties
  • Worksheet/AutoFilter

Scanning the vendor directory, the only uses of mktime/gmmktime that I see are in jpgraph, which is already problematic because it isn't supported through Composer. Again, I think this is out of scope. There is more extensive use of strtotime:

  • jpgraph
  • 1 use in phenx
  • 2 uses in symfony/finder, plus tests for symfony/finder
  • 1 use in tcpdf_static

My reading of the documentation for the strftime, localtime, date, and time functions, which take a timestamp argument, suggests that they may also be problematic after the epoch, especially when the timestamp argument is omitted. If so, this is probably a problem that PHP needs to address. For the record, Calculation/DateTime uses some of these.

Which versions of PhpSpreadsheet and PHP are affected?

AFAIK, only 32-bit PHP is affected.

oleibman
oleibman

PR #2141, which deals with many of the AutoFilter problems, has been merged. PR #2162 , which, I hope, deals with the rest of the AutofFilter problems, has been pushed.

pull request

oleibman pull request PHPOffice/PhpSpreadsheet

oleibman
oleibman

Xlsx Reader Better Namespace Handling Phase 1

There have been a number of issues concerning the handling of legitimate but unexpected namespace prefixes in Xlsx spreadsheets created by software other than Excel and PhpSpreadsheet/PhpExcel.I have studied them, but, till now, have not had a good idea on how to act on them. A recent comment https://github.com/PHPOffice/PhpSpreadsheet/issues/860#issuecomment-824926224 in issue #860 by @IMSoP has triggered an idea about how to proceed.

Gnumeric Reader was recently changed to handle namespaces better. Using that as a model, this PR begins the process of doing the same for Xlsx. Xlsx is much larger and more complicated than Gnumeric, hence the need to tackle it in multiple phases. I believe that this PR handles all of:

  • listWorkSheetNames
  • listWorkSheetInfo. Note that there was a bug in this function which would cause it to count only used columns rather than all columns. That bug is corrected.
  • active sheet
  • selected cell and top left cell
  • cell content (formulas, numbers, text)
  • hyperlinks
  • comments (partial - see below)

This PR does not address:

  • styles
  • images and charts
  • VBA and ribbons
  • many other items, I'm sure

The issue for non-standard namespacing till now has been the use of unexpected prefixes. While I was working on this change, @Lambik introduced issue #2067 PR #2068 which introduced a completely different problem - the use of unexpected URLs. That PR and the issue associated with it were quite well documented, including the supplying of a test file and tests for it. I asked if I could take a look to see if it could be integrated with my change, and the result seems to be yes, so those changes are also part of this PR.

While adding a comment to my test file, I discovered that Microsoft had added "threaded comments" as a new feature. I believe these are not yet supported by PhpSpreadsheet, and I am not going to add it, at least not now. I believe that, among other things, this will make identifying the author of a comment more difficult.

Although there are a number of Phpstan baseline changes as part of this PR, I did not attempt to resolve all Phpstan reports for Reader/Xlsx. Nor did I do anything to increase coverage. This change is already large and complex enough without those efforts.

I will add more detail as comments after I push this change.

This is:

- [x] a bugfix
- [ ] a new feature

Checklist:

Why this change is needed?

Activity icon
issue

oleibman issue comment PHPOffice/PhpSpreadsheet

oleibman
oleibman

Xlsx Reader Better Namespace Handling Phase 1

There have been a number of issues concerning the handling of legitimate but unexpected namespace prefixes in Xlsx spreadsheets created by software other than Excel and PhpSpreadsheet/PhpExcel.I have studied them, but, till now, have not had a good idea on how to act on them. A recent comment https://github.com/PHPOffice/PhpSpreadsheet/issues/860#issuecomment-824926224 in issue #860 by @IMSoP has triggered an idea about how to proceed.

Gnumeric Reader was recently changed to handle namespaces better. Using that as a model, this PR begins the process of doing the same for Xlsx. Xlsx is much larger and more complicated than Gnumeric, hence the need to tackle it in multiple phases. I believe that this PR handles all of:

  • listWorkSheetNames
  • listWorkSheetInfo. Note that there was a bug in this function which would cause it to count only used columns rather than all columns. That bug is corrected.
  • active sheet
  • selected cell and top left cell
  • cell content (formulas, numbers, text)
  • hyperlinks
  • comments (partial - see below)

This PR does not address:

  • styles
  • images and charts
  • VBA and ribbons
  • many other items, I'm sure

The issue for non-standard namespacing till now has been the use of unexpected prefixes. While I was working on this change, @Lambik introduced issue #2067 PR #2068 which introduced a completely different problem - the use of unexpected URLs. That PR and the issue associated with it were quite well documented, including the supplying of a test file and tests for it. I asked if I could take a look to see if it could be integrated with my change, and the result seems to be yes, so those changes are also part of this PR.

While adding a comment to my test file, I discovered that Microsoft had added "threaded comments" as a new feature. I believe these are not yet supported by PhpSpreadsheet, and I am not going to add it, at least not now. I believe that, among other things, this will make identifying the author of a comment more difficult.

Although there are a number of Phpstan baseline changes as part of this PR, I did not attempt to resolve all Phpstan reports for Reader/Xlsx. Nor did I do anything to increase coverage. This change is already large and complex enough without those efforts.

I will add more detail as comments after I push this change.

This is:

- [x] a bugfix
- [ ] a new feature

Checklist:

Why this change is needed?

oleibman
oleibman
started
started time in 18 hours ago
pull request

oleibman pull request PHPOffice/PhpSpreadsheet

oleibman
oleibman

Reader/Gnumeric vs. Scrutinizer

Just reviewing Scrutinizer's list of "bugs". There are 19 ascribed to me. For some, I will definitely take no action (e.g. use of bitwise operators in AND, OR, and XOR functions). However, where I can clean things up so that Scrutinizer is satisfied and the resulting code is not too contorted, I will make an attempt.

I believe this is the only one with which will involve more than 2 or 3 changes. It fixes 5 items ascribed to me, and 4 to others.

This is:

- [x] a bugfix
- [ ] a new feature

Checklist:

Why this change is needed?

Activity icon
issue

brianlmerritt issue comment PHPOffice/PhpSpreadsheet

brianlmerritt
brianlmerritt

Phpspreadsheet Charts don't work when adding multiple sheets - demo code works fine one worksheet, blank for 2+

This is:

- [x] a bug report
- [ ] a feature request
- [ ] **not** a usage question (ask them on https://stackoverflow.com/questions/tagged/phpspreadsheet or https://gitter.im/PHPOffice/PhpSpreadsheet)

What is the expected behavior?

Creating charts with multiple worksheets should not be different from creating charts with just one worksheet

What is the current behavior?

I can create one or 2 charts happily so long as I stick to the first worksheet, but as soon as I add multiple worksheets the charts written are corrupted or just blank.

What are the steps to reproduce?

Please provide a Minimal, Complete, and Verifiable example of code that exhibits the issue without relying on an external Excel file or a web server:

If you run the code below with $stickToOneSheet set to true, the code runs fine.

There are several options for adding a worksheet and 2 (different?) $writers and none of them produce working charts if there is more than one worksheet.

<?php

require __DIR__ . '/vendor/autoload.php';
use PhpOffice\PhpSpreadsheet\Chart\Chart;
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
use PhpOffice\PhpSpreadsheet\Chart\Legend;
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
use PhpOffice\PhpSpreadsheet\Chart\Title;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;



$stickToOneSheet = true;
$useNewWriterFactory = false;
$cloneNewWorksheet = true; // Only relevant if multiple sheets
$multipleCharts = true;
$title = 'newworksheet';

$spreadsheet = new Spreadsheet();

if ($stickToOneSheet) {
    $worksheet = $spreadsheet->getActiveSheet();

} elseif ($cloneNewWorksheet) {
    $worksheet1 = $spreadsheet->getActiveSheet();
    $worksheet = clone $worksheet1;
    $worksheet->setTitle($title);
    $spreadsheet->addSheet($worksheet,1);
} elseif ($useNewWriterFactory) {

    $worksheet = new Worksheet($spreadsheet, $title);
    $spreadsheet->addSheet($worksheet,1);
} else {
    echo "Sorry, no idea what you want to test";
    die;
}


// Todo generate data in this format
$data = [  // Note this data need to be transposed
    ['Tutor Dashboard Report for someone@example.com'],
    [''],
    ['','Course Minutes','Quiz Minutes','Book Minutes','Other Minutes','Panopto Minutes','Total Minutes', 'Graded Activities', '# Vidoes Watched', '# Watched Completely', 'Quartile Rank'],
    ['Sep20',22,23,65,60,37,256,2,3,2,1],
    ['Oct20',18,39,47,68,38,256,2,3,2,1],
    ['Nov20',12,15,43,67,38,256,4,3,2,3],
    ['Dec20',4,1,154,0,21,256,2,3,2,1],
    ['Jan21',22,15,38,18,10,256,4,4,2,4],
    ['Feb21',18,39,47,68,38,256,2,3,2,1],
    ['Mar21',12,15,43,67,38,256,2,5,2,1],
    ['Apr21',4,1,154,14,21,256,2,1,1,1],
    ['May21',18,39,47,68,38,256,2,3,2,2],
];


$worksheet->fromArray($data);


$num_columns = count($data[2]);
$num_rows = count($data)-3;
echo "\n\nColumns: $num_columns, Rows: $num_rows\n\n";

// Set the Labels for each data series we want to plot
//     Datatype
//     Cell reference for data
//     Format Code
//     Number of datapoints in series
//     Data values
//     Data Marker
//Todo set start values to calculations
$dataSeriesLabels = [
    new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$B$3', null, 1), // Course
    new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$C$3', null, 1), // Quiz
    new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$D$3', null, 1), // Books
    new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$E$3', null, 1), // Other
    new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$F$3', null, 1), // Panopto
];
// Set the X-Axis Labels
//     Datatype
//     Cell reference for data
//     Format Code
//     Number of datapoints in series
//     Data values
//     Data Marker
$xAxisTickValues = [
    //Todo set values to calculations
    new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$A$4:$A$12', null, 4), // Q1 to Q4
];
// Set the Data values for each data series we want to plot
//     Datatype
//     Cell reference for data
//     Format Code
//     Number of datapoints in series
//     Data values
//     Data Marker
//Todo set start and end values to calculations
$dataSeriesValues = [
    new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$B$4:$B$12', null, 4),
    new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$4:$C$12', null, 4),
    new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$D$4:$D$12', null, 4),
    new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$E$4:$E$12', null, 4),
    new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$F$4:$F$12', null, 4),
];

// Build the dataseries
$series = new DataSeries(
    DataSeries::TYPE_BARCHART, // plotType
    DataSeries::GROUPING_STACKED, // plotGrouping
    range(0, count($dataSeriesValues) - 1), // plotOrder
    $dataSeriesLabels, // plotLabel
    $xAxisTickValues, // plotCategory
    $dataSeriesValues        // plotValues
);
// Set additional dataseries parameters
//     Make it a vertical column rather than a horizontal bar graph
$series->setPlotDirection(DataSeries::DIRECTION_COL);

// Set the series in the plot area
$plotArea = new PlotArea(null, [$series]);
// Set the chart legend
$legend = new Legend(Legend::POSITION_RIGHT, null, false);

$title = new Title('Tutor Dashboard - brmerritt@rvc.ac.uk'); // Todo add student email
$yAxisLabel = new Title('Learning Minutes');

// Create the chart
$chart = new Chart(
    'chart1', // name
    $title, // title
    $legend, // legend
    $plotArea, // plotArea
    true, // plotVisibleOnly
    DataSeries::EMPTY_AS_GAP, // displayBlanksAs
    null, // xAxisLabel
    $yAxisLabel  // yAxisLabel
);

// Set the position where the chart should appear in the worksheet
$chart->setTopLeftPosition('A'.($num_rows + 7));
$chart->setBottomRightPosition('M'.($num_rows + 22));

// Add the chart to the worksheet
$worksheet->addChart($chart);

if ($multipleCharts) {


    // OK, try adding another chart!
    $dataSeriesLabels2 = [
        //new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$G$3', null, 1), // Total Minutes - ignore!
        new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$H$3', null, 1), // Graded Activities
        new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$I$3', null, 1), // Videos Watched
        new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$J$3', null, 1), // Watched Completely
        new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$K$3', null, 1), // Quartile Ranking
    ];
    $xAxisTickValues2 = [
        //Todo set values to calculations
        new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$A$4:$A$12', null, 4), // Q1 to Q4
    ];

    //Todo set start and end values to calculations
    $dataSeriesValues2 = [
        new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$H$4:$H$12', null, 4),
        new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$I$4:$I$12', null, 4),
        new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$J$4:$J$12', null, 4),
        new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$K$4:$K$12', null, 4),
        //new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$F$4:$F$12', null, 4),
    ];

    // Build the dataseries
    $series2 = new DataSeries(
        DataSeries::TYPE_BARCHART, // plotType
        DataSeries::GROUPING_CLUSTERED, // plotGrouping
        range(0, count($dataSeriesValues2) - 1), // plotOrder
        $dataSeriesLabels2, // plotLabel
        $xAxisTickValues2, // plotCategory
        $dataSeriesValues2        // plotValues
    );
    // Set additional dataseries parameters
    //     Make it a vertical column rather than a horizontal bar graph
    $series2->setPlotDirection(DataSeries::DIRECTION_COL);

    // Set the series in the plot area
    $plotArea2 = new PlotArea(null, [$series2]);
    // Set the chart legend
    $legend2 = new Legend(Legend::POSITION_RIGHT, null, false);

    $title2 = new Title('Graded Activities, Videos Watched, and Quartile Ranking'); // Todo add student email
    $yAxisLabel2 = new Title('Number of Each');


    $chart2 = new Chart(
        'chart2', // name
        $title2, // title
        $legend2, // legend
        $plotArea2, // plotArea
        true, // plotVisibleOnly
        DataSeries::EMPTY_AS_GAP, // displayBlanksAs
        null, // xAxisLabel
        $yAxisLabel2  // yAxisLabel
    );
    // Set the position where the chart should appear in the worksheet
    $chart2->setTopLeftPosition('A' . ($num_rows + 29));
    $chart2->setBottomRightPosition('M' . ($num_rows + 44));

    // Add the chart to the worksheet
    $worksheet->addChart($chart2);
}

// Save Excel file

$filename = "test_col1_stacked_7.xlsx";
if ($useNewWriterFactory) {
    $writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
} else {
    $writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
}

$writer->setIncludeCharts(true);
$callStartTime = microtime(true);
$writer->save($filename);
return 0;

// add code that show the issue here...

$stickToOneSheet = false; // Change the code above and the charts will not have visible data or be corrupted.

Which versions of PhpSpreadsheet and PHP are affected?

PHP 7.4.12 Phpspreadsheet versions 1.16 and 1.18 Excel version 2105 build 14026...

brianlmerritt
brianlmerritt

No worries - using someone's email name as part of the chart name (probably the @symbol) messed it up.

started
started time in 22 hours ago
open pull request

jarrettj wants to merge PHPOffice/PhpSpreadsheet

jarrettj
jarrettj

When image source is a URL, store the URL for use during extraction.

When image source is a link store the link.

This is:

- [ ] a bugfix
- [x] a new feature

Checklist:

Why this change is needed?

Described in issue https://github.com/PHPOffice/PhpSpreadsheet/issues/1997.

jarrettj
jarrettj

Added a test for the reader, please have a look and see if it is sufficient. Thanks.

pull request

jarrettj merge to PHPOffice/PhpSpreadsheet

jarrettj
jarrettj

When image source is a URL, store the URL for use during extraction.

When image source is a link store the link.

This is:

- [ ] a bugfix
- [x] a new feature

Checklist:

Why this change is needed?

Described in issue https://github.com/PHPOffice/PhpSpreadsheet/issues/1997.

started
started time in 22 hours ago
Activity icon
fork

antonga23 forked PHPOffice/PHPExcel

⚡ ARCHIVED
antonga23 Updated
fork time in 23 hours ago
started
started time in 23 hours ago
Activity icon
issue

khongshao issue comment PHPOffice/PHPWord

khongshao
khongshao

Word Chinese PDF contains garbled code

Word content contains Chinese, when converted to PDF, all Chinese show ???

khongshao
khongshao

以MPDF为例,在vendor/phpoffice/phpword/src/PhpWord/Writer/PDF/MPDF.php,73行后面加上$pdf->autoScriptToLang = true; $pdf->autoLangToFont = true;,就可以解决乱码问题