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

WorkbookProtection corrupts Spreadsheet for Excel 2019 #601

Closed
DizTortion opened this issue Jun 21, 2019 · 7 comments
Closed

WorkbookProtection corrupts Spreadsheet for Excel 2019 #601

DizTortion opened this issue Jun 21, 2019 · 7 comments

Comments

@DizTortion
Copy link

DizTortion commented Jun 21, 2019

Spreadsheets saved with Excel 2019 get corrupted as soon as you add a WorkbookProtection.

Information

  • .NET Target: .NET 3.5
  • DocumentFormat.OpenXml Version: 2.9.1, 2.10.0-beta0001

Repro

Create an empty spreadsheet in Excel 2019. Perform the following operation:

using (var document = SpreadsheetDocument.Open("...", true) {
  document.WorkbookPart.Workbook.WorkbookProtection = new WorkbookProtection();
}

Open the spreadsheet in Excel 2019.

Observed

Excel fails to open and repair the file.

Exception

The resulting workbook.xml contains the newly added x:workbookProtection followed by the x:revisionPtr.

<x:workbookProtection />
<xr:revisionPtr revIDLastSave="0" documentId="13_ncr:1_{4BF1E7C4-2F1B-4756-81DA-B102ED8D212D}" xr6:coauthVersionLast="36" xr6:coauthVersionMax="36" xr10:uidLastSave="{00000000-0000-0000-0000-000000000000}" />

Manually changing the order (unzip/edit/zip) repairs the file.

<xr:revisionPtr revIDLastSave="0" documentId="13_ncr:1_{4BF1E7C4-2F1B-4756-81DA-B102ED8D212D}" xr6:coauthVersionLast="36" xr6:coauthVersionMax="36" xr10:uidLastSave="{00000000-0000-0000-0000-000000000000}" />
<x:workbookProtection />

Expected

File should not get corrupted.

@twsouthwick
Copy link
Member

@DizTortion Thanks for the report. I'm a little confused by which version of excel you are referring to throughout. Can you update your repro to be explicit as to the version?

This is probably from the new 2016 features that have been brought online.

@DizTortion
Copy link
Author

@twsouthwick Hi, I updated the issue and removed references to versions other than Excel 2019. I just tried to emphasize that the code worked while we used Excel 2010. Now that we upgraded to Excel 2019 we are seeing corrupted files.

@twsouthwick
Copy link
Member

Thanks @DizTortion for the feedback. @tomjebo this seems a bit more schema related - can you check if the ordering has changed between 2010 and 2019?

@S1r-Lanzelot
Copy link

Any update on this @twsouthwick ? We ran into the same issue, ended up building our document with openxml and then using com to do the protection. 🤦‍♂

@DizTortion
Copy link
Author

DizTortion commented Dec 9, 2019

@S1r-Lanzelot Maybe give this workaround a try. Make your Spreadsheet modifications and close the stream. Then pass that stream (variable memoryStream) to the using block below.

It checks if there is a workbook protection and swaps its position with the revisionPtr. No COM interop required.

// TODO: workaround (see https://github.com/OfficeDev/Open-XML-SDK/issues/601)
using (var package = Package.Open(memoryStream, FileMode.Open))
{
    var xmlDocument = new XmlDocument();

    var part = package.GetPart(new Uri("/xl/Workbook.xml", UriKind.Relative));

    using (var oldPartStream = part.GetStream())
    {
        xmlDocument.Load(oldPartStream);

        var xmlNamespaceManager = new XmlNamespaceManager(xmlDocument.NameTable);
        xmlNamespaceManager.AddNamespace(
            "x",
            "http://schemas.openxmlformats.org/spreadsheetml/2006/main");
        xmlNamespaceManager.AddNamespace(
            "xr",
            "http://schemas.microsoft.com/office/spreadsheetml/2014/revision");

        var workbook = xmlDocument.DocumentElement
            .SelectSingleNode("/x:workbook", xmlNamespaceManager);
        var revisionPtr = xmlDocument.DocumentElement
            .SelectSingleNode("/x:workbook/xr:revisionPtr", xmlNamespaceManager);
        var workbookProtection = xmlDocument.DocumentElement
            .SelectSingleNode("/x:workbook/x:workbookProtection", xmlNamespaceManager);

        if (revisionPtr != null)
        {
            workbook.RemoveChild(revisionPtr);
            workbook.InsertBefore(revisionPtr, workbookProtection);

            using (var newPartStream = part.GetStream(FileMode.Create))
            {
                xmlDocument.Save(newPartStream);
            }
        }
    }
}

@github-actions
Copy link

Stale issue message

@DizTortion
Copy link
Author

Any progress on this one? I'd be happy to provide more information if required.

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

No branches or pull requests

3 participants