Skip to content

Writer WPS: basic support of Microsoft Works documents - #2929

Open
businessarshgoyal wants to merge 3 commits into
PHPOffice:masterfrom
businessarshgoyal:devin/1788015204-wps-writer
Open

Writer WPS: basic support of Microsoft Works documents#2929
businessarshgoyal wants to merge 3 commits into
PHPOffice:masterfrom
businessarshgoyal:devin/1788015204-wps-writer

Conversation

@businessarshgoyal

Copy link
Copy Markdown

Description

Adds a WPS writer producing documents for the word processor of Microsoft Works 7 and 8, ie an OLE compound file whose CONTENTS stream holds the CHNKWKS chunks of the document, as described by the format notes linked in the issue and implemented by libwps (WPS8Parser).

$writer = IOFactory::createWriter($phpWord, 'WPS');
$writer->save(__DIR__ . '/sample.wps');

What is added:

  • Shared\OLEWrite: a small compound file (CFB v3, 512 bytes sectors) writer, counterpart of the existing Shared\OLERead, building the FAT, the mini FAT, the mini stream and the red-black directory from a set of named streams. No new dependency.
  • Writer\WPS and Writer\WPS\Part\Contents, following the structure of the RTF writer: the part writes the stream header, the chunk index and the TEXT and FONT chunks; the text is UTF-16LE, paragraphs are terminated by \r and page breaks by \f.
  • Registration of WPS in IOFactory::createWriter().

First iteration scope, as suggested in the issue: text and basic paragraph output. Text, text runs, titles, links, list items, text breaks, page breaks and the text of the cells of a table are written as paragraphs. Not supported yet (silently ignored, no error): character and paragraph styles, table and list structure, images, objects, headers, footers, footnotes, endnotes, comments, table of contents, document properties, form fields, and reading .wps files.

About #2769

I looked at #2769 first and did not build on it: it writes a ZIP package of ODF-like XML parts (content.xml, styles.xml, META-INF/manifest.xml), which is not the Microsoft Works binary format the issue asks for — such a file is not an OLE document and is not recognised by Works or by libwps-based readers (LibreOffice). This PR writes the CONTENTS/CHNKWKS stream instead, so the two approaches do not share code.

Validation

Besides the unit tests, the generated files were checked against the reference implementation, wps2text (libwps 0.4.12), which extracts the expected text, and against olefile/file(1), which validate the compound file structure.

Fixes #69

/claim #69

Checklist:

  • My CI is 🟢
  • I have covered by unit tests my new code (check build/coverage for coverage report)
  • I have updated the documentation to describe the changes
  • I have updated the changelog

devin-ai-integration Bot and others added 2 commits August 29, 2026 14:53
Add a WPS writer producing an OLE compound file whose CONTENTS stream
holds the CHNKWKS chunks of the document, with the text and the page
breaks of the elements.

Co-Authored-By: business.arshgoyal@gmail.com <business.arshgoyal@gmail.com>
Co-Authored-By: business.arshgoyal@gmail.com <business.arshgoyal@gmail.com>
@coveralls

coveralls commented Aug 29, 2026

Copy link
Copy Markdown

Coverage Status

coverage: 96.569% (-0.05%) from 96.614% — businessarshgoyal:devin/1788015204-wps-writer into PHPOffice:master

@Progi1984 Progi1984 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than adding file src/PhpWord/Shared/OLEWrite.php, could use PhpOffice/Common ?

@businessarshgoyal

Copy link
Copy Markdown
Author

Happy to, but PhpOffice/Common only has Common\Microsoft\OLERead on master (1.0.5), there is no compound file writer in it, and PHPWord dropped the phpoffice/common requirement back in 67b1598 (Jan 2021), so pulling it in for this would both add a dependency and still need the writer to be written somewhere.

Two ways I can go, tell me which you prefer:

  1. I open a PR on PhpOffice/Common adding Common\Microsoft\OLEWrite as the counterpart of OLERead, then this PR requires phpoffice/common and drops src/PhpWord/Shared/OLEWrite.php. Cleanest long term since PHPPresentation and PHPWord could share it, but it blocks this PR on a Common release
  2. It stays in PHPWord as Shared\OLEWrite, marked @internal, and moves to Common later without a breaking change for users

Default is 2 unless you say otherwise

Written by Devin

@Progi1984

Copy link
Copy Markdown
Member

Go to 1

@businessarshgoyal

Copy link
Copy Markdown
Author

Done: PHPOffice/Common#65 adds Common\Microsoft\OLEWrite (round-trip tested against OLERead; phpunit, phpstan level 7 and phpmd pass).

Once that lands and Common tags a release, I'll update this PR to require phpoffice/common and delete src/PhpWord/Shared/OLEWrite.php, pointing Writer\MsDoc at the Common class. I've left the copy in place here for now so this PR keeps building — say the word if you'd rather I switch it to dev-master immediately instead of waiting for the tag.

Written by Devin

Co-Authored-By: business.arshgoyal@gmail.com <business.arshgoyal@gmail.com>
@Progi1984

Copy link
Copy Markdown
Member

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

Implement WPS Writer

3 participants