Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Notes crash PPTX unless they're on each slide #83

Open
JewrassicPark opened this issue Jan 9, 2015 · 26 comments
Open

Notes crash PPTX unless they're on each slide #83

JewrassicPark opened this issue Jan 9, 2015 · 26 comments

Comments

@JewrassicPark
Copy link
Contributor

JewrassicPark commented Jan 9, 2015

Basic method is

$pp = new PhpPowerpoint();
//don't put any notes on the first slide 
$slide = $pp->createSlide();
$note = $slide->getNote();
$text = $note->createRichTextShape()->setHeight(300)->setWidth(600);
$text->createTextRun("Any Note");
$oWriterPPTX = IOFactory::createWriter($pp, 'PowerPoint2007');
$oWriterPPTX->save($savePath);      

This causes Office PowerPoint to crash.

It can be worked around by adding a non empty note to every slide.

e.g. this works:

$pp = new PhpPowerpoint();
//putting a note on the first slide
$slide  = $pp->getActiveSlide();
$note = $slide->getNote();
$text = $note->createRichTextShape()->setHeight(300)->setWidth(600);
$text->createTextRun("Any Note");
//putting a note on the second slide 
$slide = $pp->createSlide();
$note = $slide->getNote();
$text = $note->createRichTextShape()->setHeight(300)->setWidth(600);
$text->createTextRun("Any Note");
$oWriterPPTX = IOFactory::createWriter($pp, 'PowerPoint2007');
$oWriterPPTX->save($savePath);      

Notes generated with PHPPowerpoint show up in the pptx zip according to slide

noteSlide2.xml => slide # 2, noteSlideX.xml => slide # x

When created with MS Office, the noteSlides are just numbered sequentially

noteSlide1.xml => corresponds to some slide not necessarily #1 , noteSlide2.xml => same thing

They also have a _rels relationship folder and a noteSlideMaster folder. I couldn't work out the exact mapping or how to avoid this crashing issues. Currently I'm using the workaround.

@JewrassicPark
Copy link
Contributor Author

Another notes bug: Inconsistently when generating large reports, a notesslide relationship in the slide rels dir file for a slide will have the wrong slide number (which currently has to be the same as the slide because every slide needs notes if one slide has notes). This causes office to show the repair dialogue. This is extremely inconsistent. I'll generate the same powerpoint twice and might receive this error on one.

@Progi1984
Copy link
Member

@JewrassicPark
I generate a file with PHPPowerPoint (the last version of the develop branch).
I open the generated file with MS Office PowerPoint Viewer : No problem.
I validate the generated file with Open XML SDK 2.5 Productivity Tool for Microsoft Office : No problem.

@JewrassicPark
Copy link
Contributor Author

I still get the same initial bug with latest dev branch

It doesn't crash if notes are on every slide:

    $p = new Presentation();
    $p->debug = true;
    $p->addSlide(); 
    $p->addNote(ARRAY('t'=>'testing'));
    $p->addSlide(); 
    $p->addNote(ARRAY('t'=>'testing'));
    $file = $p->save();

But it crashes consistently immediately upon opening in PowerPoint 2013 if one slide has notes and the other doesnt

    $p = new Presentation();
    $p->debug = true;
    $p->addSlide(); 
    //$p->addNote(ARRAY('t'=>'testing'));
    $p->addSlide(); 
    $p->addNote(ARRAY('t'=>'testing'));
    $file = $p->save();

The other bug with the numbering was only observed when generating large powerpoints (50+ slides) and it wasn't consistent (generated same powerpoint twice, one needed to be repaired and one didn't)

@Progi1984
Copy link
Member

@JewrassicPark Firstly, I try to reproduce your first bug (before bug of numerotation);
But your code use home made methods, I suppose.
So I use this code

$pp = new PhpPowerpoint();
$slide = $pp->createSlide();

$slide = $pp->createSlide();
$note = $slide->getNote();
$text = $note->createRichTextShape()->setHeight(300)->setWidth(600);
$text->createTextRun("Any Note");

$oWriterPPTX = IOFactory::createWriter($pp, 'PowerPoint2007');
$oWriterPPTX->save('#83/Sample83.pptx');

Always ok with the PPTX Viewer, the SDK Validator and LibreOffice.
Without reproducing this bug, I can't fix it.

@JewrassicPark
Copy link
Contributor Author

That code exactly immediately crashes my Powerpoint 2013.

To not crash it, I have to add a note to the first slide you create and the first slide created automatically by the constructor

    $pp = new PhpPowerpoint();
    $slide = $pp->getActiveSlide();
    $note = $slide->getNote();
    $text = $note->createRichTextShape()->setHeight(300)->setWidth(600);
    $text->createTextRun("Any Note");


    $slide = $pp->createSlide();
    $note = $slide->getNote();
    $text = $note->createRichTextShape()->setHeight(300)->setWidth(600);
    $text->createTextRun("Any Note");

    $slide = $pp->createSlide();
    $note = $slide->getNote();
    $text = $note->createRichTextShape()->setHeight(300)->setWidth(600);
    $text->createTextRun("Any Note");

    $oWriterPPTX = IOFactory::createWriter($pp, 'PowerPoint2007');
    $oWriterPPTX->save("/$path/test-ppt.pptx");

@Progi1984
Copy link
Member

@JewrassicPark No problem with the SDK Validator and LibreOffice... :S

Have you a sample file generated with Powerpoint 2013 with a simple note for looking differences ?

@Progi1984
Copy link
Member

@JewrassicPark I just tried on a PPT2007 and no problem with your code and the generated file.

@Progi1984
Copy link
Member

@JewrassicPark PHPPowerPoint 0.4.0 has been released. I would like to solve your issue for 0.5.0. Could you answer to my question ?

@JewrassicPark
Copy link
Contributor Author

Sorry my job doesn't afford me a lot of chances to work on the phpowerpoint code we use. I just ran two tests. Both with two slides. The first had notes only on the second slide, and that worked which goes against my previous findings. The second one had notes only on the first slide, this caused the powerpoint to either need to be repaired or just froze and crashed. Using office 2013.

@Progi1984
Copy link
Member

@JewrassicPark Thanks for your feedback

So this code could crash Office 2013 :

   $pp = new PhpPowerpoint();
    $slide = $pp->getActiveSlide();
    $note = $slide->getNote();
    $text = $note->createRichTextShape()->setHeight(300)->setWidth(600);
    $text->createTextRun("Any Note");


    $slide = $pp->createSlide();
    $note = $slide->getNote();
    $text = $note->createRichTextShape()->setHeight(300)->setWidth(600);
    $text->createTextRun("Any Note");

    $slide = $pp->createSlide();

    $oWriterPPTX = IOFactory::createWriter($pp, 'PowerPoint2007');
    $oWriterPPTX->save("/$path/test-ppt.pptx");

The generated file : https://www.dropbox.com/s/28sipncx8vr2e6k/83.pptx?dl=0

  • No problem with LibreOffice
  • Have you got the problem with this file on Office 2007 / 2013 ?

@Progi1984
Copy link
Member

@JewrassicPark PHPPowerPoint 0.6.0 has been released. I would like to solve your issue for 0.7.0. Could you answer to my question ?

@JewrassicPark
Copy link
Contributor Author

@Progi1984 Sorry, I've had a request for this feature at work again and I'll revisit this issue shortly.

@JewrassicPark
Copy link
Contributor Author

I can consistently get it to crash if there is no notes on the first slide but there are notes on any of the next slides. Using 0.6.0 with Powerpoint 2013 on Windows. I understand this is contrary to the previous tests. My current workaround is to force a slide to have blank notes by default.
To be clear the powerpoints are generated via PHP on a CENTOS server but I'm opening them on Windows.

@JewrassicPark
Copy link
Contributor Author

I'm getting reports from my users that powerpoints with notes enabled are breaking more often when generating. I can't say for sure that it's this feature but it's really the only major change I've made to my codebase in awhile. I think there's got to be something implemented incorrectly with notes still.

@Progi1984
Copy link
Member

@JewrassicPark : So this code should be generating a crashed file ?

  $pp = new PhpPowerpoint();
  $slide1= $pp->getActiveSlide();
  // With no notes

  $slide = $pp->createSlide();
  $note = $slide->getNote();
  $text = $note->createRichTextShape()->setHeight(300)->setWidth(600);
  $text->createTextRun("Any Note");

  $slide = $pp->createSlide();

  $oWriterPPTX = IOFactory::createWriter($pp, 'PowerPoint2007');
  $oWriterPPTX->save("/$path/test-ppt.pptx");

@JewrassicPark
Copy link
Contributor Author

Yes I believe so, that was causing consistent crashing on open for me. If I use my workaround to put a dummy note on every slide, it still seems to be causing sporadic issues.

@Progi1984
Copy link
Member

@JewrassicPark Could you check this bug with the last version of the develop branch ?

@JewrassicPark
Copy link
Contributor Author

Yeah it's still present.

I tried a few combinations involving three slides.

slide 1 = s1, slide2 = s2, slide3 = s3

s1 with notes, s2 with notes, s2 no notes = Works
s1 with notes, s2 no notes, s3 with notes = Works
s1 with no notes, s2 with notes, s3 with notes = Crashes on opening ppt
s1 with no notes, s2 with notes, s3 no notes = Crashes on opening ppt

Even when I was forcing every slide to have notes by default (a workaround), I was getting user reports of slides being broken. Perhaps it's some kind of indexing issue.

@Progi1984
Copy link
Member

@JewrassicPark Shit, i try with a sample code :

// Create new PHPPresentation object
echo date('H:i:s') . ' Create new PHPPresentation object' . EOL;
$objPHPPresentation = new PhpPresentation();
$oLayout = $objPHPPresentation->getLayout();

// Set properties
echo date('H:i:s') . ' Set properties' . EOL;
$objPHPPresentation->getDocumentProperties()->setCreator('PHPOffice')->setLastModifiedBy('PHPPresentation Team')->setTitle('Sample 01 Title')->setSubject('Sample 01 Subject')->setDescription('Sample 01 Description')->setKeywords('office 2007 openxml libreoffice odt php')->setCategory('Sample Category');

// Create slide
echo date('H:i:s') . ' Create slide' . EOL;
$oSlide1 = $objPHPPresentation->getActiveSlide();
echo date('H:i:s') . ' Create slide' . EOL;
$oSlide2 = $objPHPPresentation->createSlide();
echo date('H:i:s') . ' Create slide' . EOL;
$oSlide3 = $objPHPPresentation->createSlide();

// Set Note
echo date('H:i:s') . ' Set Note' . EOL;
$oNote1 = $oSlide2->getNote();

$oRichText = $oNote1->createRichTextShape()
    ->setHeight($oLayout->getCY($oLayout::UNIT_PIXEL))
    ->setWidth($oLayout->getCX($oLayout::UNIT_PIXEL))
    ->setOffsetX(170)
    ->setOffsetY(180);
$oRichText->createTextRun('A class library');
$oRichText->createParagraph()->createTextRun('Written in PHP');
$oRichText->createParagraph()->createTextRun('Representing a presentation');
$oRichText->createParagraph()->createTextRun('Supports writing to different file formats');

And no problem with PowerPoint :
screen shot 05-21-16 at 03 28 pm

May be it's a problem of version, etc...

Could you send me a sample of PPTX which crashes and its code ?

@JewrassicPark
Copy link
Contributor Author

I used the exact sample code you have above with the latest dev branch

http://www.filedropper.com/crashesonstartpowerpoint2013

it hard crashes immediately for me on file open consistently.

Powerpoint 2013 on Windows 10

@Progi1984
Copy link
Member

@JewrassicPark : Just for keeping the file on Github : crashesOnStartPowerpoint2013.pptx

No problem with PowerPoint 2007.
And it's valid againt MS Office 2013 format :
screen shot 05-31-16 at 10 56 pm

@JewrassicPark
Copy link
Contributor Author

Perhaps you can send me a file generated with the same code and I can confirm it's not an issue with my servers

@davemulder
Copy link

@Progi1984 — I've been tracking down a similar issue as @JewrassicPark, except with Mac Keynote. The presence of any programmatically generated slide notes appears to create a PPTX that Keynote, at least version 6.6.2, does not want to open (produces a generic error). This was also true using the code and file you provided in this thread.

I know that your work is geared around PowerPoint, specifically, but I wanted to give you a heads up as it could be related to the PowerPoint crashing issue being discussed here.

@Progi1984 Progi1984 modified the milestones: 0.8.0, Waiting For Answer Aug 31, 2016
@davemulder
Copy link

Tested with PHPPresentation 0.7 and what I noted in my previous comment is still an issue with Keynote. Any programmatically created notes seem to generate a PPTX file that cannot be opened in Keynote.

Based on thorough inspection of the PHPPresentation-generated PPTX, it seems that it's missing "notesMasters" despite having slide notes present. The PPTX still validates (using the Open XML validation tool) but evidently that's not good enough for Keynote.

@Progi1984 Progi1984 modified the milestones: 0.8.0, 0.9.0 Apr 3, 2017
@Progi1984 Progi1984 modified the milestones: 0.9.0, 0.10.0 Jul 5, 2017
@Progi1984 Progi1984 modified the milestones: 1.0.0, 1.1.0 Sep 9, 2021
@NigelSwinson
Copy link

FYI, testing with the develop branch, on Windows, and this issue remains:

<?php

include_once 'Sample_Header.php';

use PhpOffice\PhpPresentation\PhpPresentation;
use PhpOffice\PhpPresentation\Style\Alignment;
use PhpOffice\PhpPresentation\Style\Color;
$objPHPPresentation = new PhpPresentation();

$currentSlide = $objPHPPresentation->getActiveSlide();
$oNote = $currentSlide->getNote();
// ### If you don't include this line, it will crash
//$oRichText = $oNote->createRichTextShape();

// Create second slide with a note
$currentSlide = $objPHPPresentation->createSlide();
$oNote = $currentSlide->getNote();
$oRichText = $oNote->createRichTextShape();
$oRichText->createTextRun('Second note');

// Save file
echo write($objPHPPresentation, basename(__FILE__, '.php'), $writers);
if (!CLI) {
    include_once 'Sample_Footer.php';
}

I haven't tried the pull request, but will do so now and see if that addresses the issue.

@NigelSwinson
Copy link

NigelSwinson commented Apr 6, 2024

A fix: in Writer/PowerPoint2007.php add this method. It will scan the presentation seeing if any note exists, and if it does, it will add a blank RichTextShape note to the slide preventing the crash.

// ### Add a using statement so we can reference the Note class
use PhpOffice\PhpPresentation\Slide\Note;

....

    // ### A new private member of the PowerPoint2007 class
    private function insertNecessaryNotes() {
    	$oPresentation = $this->getPhpPresentation();
    	// Work out if we need to write any notes
    	// ### https://github.com/PHPOffice/PHPPresentation/issues/83 If we only write out notes files for the slides that have notes, then Powerpoint will crash.
    	// . e.g. if your slide 5 is the first slide to have a note, meaning you will write out slide5.xml, but didn't write out slide1.xml-slide4.xml then Powerpoint
    	// will crash. To fix, we first scan through the deck to see if anyone wants to write any notes, and anyone does, we make sure all slides have an empty note.
    	$bMustWriteNotes = false;
    	foreach ($oPresentation->getAllSlides() as $idx => $oSlide) {
    		$oNote = $oSlide->GetNote();
    		if (!($oNote instanceof Note)) continue;
    		if (count($oSlide->getNote()->getShapeCollection()) == 0) continue;
    		// Stop if we find any slide which has a note.
    		$bMustWriteNotes = true;
    		break;
    	}
    	
    	// If we must write notes, then make sure all slides have notes.
    	if ($bMustWriteNotes) {
    		foreach ($oPresentation->getAllSlides() as $idx => $oSlide) {
    			if (!($oSlide->getNote() instanceof Note)) continue;
    			$oNote = $oSlide->getNote();
    			if (count($oNote->getShapeCollection()) > 0) continue;
    			// If we don't provoke the need for a notes slide, then this powerpoint will crash
    			$oNote->createRichTextShape();
    		}
    	}
    }

Then call it in save() just before the foreach loop().

        ksort($arrayFiles);

        // ### Call here, before we start writing any content.
        $this->insertNecessaryNotes();
        
        foreach ($arrayFiles as $o) {
            $oService = $o->newInstance();
            $oService->setZip($oZip);
            $oService->setPresentation($oPresentation);
            $oService->setDrawingHashTable($this->getDrawingHashTable());
            $oZip = $oService->render();
            unset($oService);
        }

@Progi1984 Progi1984 modified the milestones: 1.1.0, 1.2.0 Sep 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

4 participants