npoi icon indicating copy to clipboard operation
npoi copied to clipboard

Support DOCM file type

Open TomLingWu opened this issue 5 months ago • 2 comments

NPOI Version Used

Version 2.6.2

File Type

  • [ ] XLSX
  • [ ] XLS
  • [X] DOCX
  • [ ] XLSM
  • [ ] OTHER

Use Case

We use the XWPFDocument , and want to generate *.docm document format with some VBA macros enabled, it also uses hyperlinks and table of contents etc. The current official supported file types only include DOCX and XLSM, but without DOCM. Could we add the support for DOCM file type, please?

Description

One of the uses of the VBA macro is to avoid the EnforceUpdateFields() to ask two questions when opening the docx file, and the user directly saves it doesn't work since Word considers the updated fields are not a real change. So the workaround using a macro is like this:

Sub AutoOpen()
        ActiveDocument.TablesOfContents(1).Update
        ActiveDocument.TablesOfContents(1).UpdatePageNumbers
End Sub

Notes:

My test code with a hyperlink: MS Word cannot open the saved hyperlink-docm.docm.

using NPOI.XWPF.UserModel;

class Program
{
    static void Main(string[] args)
    {
        try
        {
            using var doc = new XWPFDocument();

            var paragraph = doc.CreateParagraph();
            var run = paragraph.CreateRun();
            run.SetText("This is a text paragraph having ");

            AddHyperlinkToParagraph(paragraph, @"https://www.google.com", "a link to Google");

            run = paragraph.CreateRun();
            run.SetText(" in it.");

            using var out1 = new FileStream(@"hyperlink-docm.docm", FileMode.Create);
            doc.Write(out1);

            using var out2 = new FileStream(@"hyperlink-docx.docx", FileMode.Create);
            doc.Write(out2);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }

    static XWPFHyperlinkRun CreateHyperlinkRun(XWPFParagraph paragraph, string url)
    {
        var rId = paragraph.Document.GetPackagePart().AddExternalRelationship(
            url,
            XWPFRelation.HYPERLINK.Relation
        ).Id;

        return paragraph.CreateHyperlinkRun(rId);
    }

    static void AddHyperlinkToParagraph(XWPFParagraph paragraph, string url, string displayText)
    {
        var hyperlinkRun = CreateHyperlinkRun(paragraph, url);

        // Set the text of the run to the display text
        hyperlinkRun.SetText(displayText);
        hyperlinkRun.Underline = UnderlinePatterns.Single;
        hyperlinkRun.SetColor("0000FF");
    }
}

TomLingWu avatar Jan 11 '24 00:01 TomLingWu

It seems there is NO option to specify the 'ContentType' when to create the instance of XWPFDocument. And it would be nice to inject a parameter and let use to specify document type in the constructor.

/** * Create a new WordProcessingML package and Setup the default minimal content */ protected static OPCPackage NewPackage() { try { OPCPackage pkg = OPCPackage.Create(new MemoryStream()); // Main part PackagePartName corePartName = PackagingUriHelper.CreatePartName(XWPFRelation.DOCUMENT.DefaultFileName); // Create main part relationship pkg.AddRelationship(corePartName, TargetMode.Internal, PackageRelationshipTypes.CORE_DOCUMENT); // Create main document part pkg.CreatePart(corePartName, XWPFRelation.DOCUMENT.ContentType);

          pkg.GetPackageProperties().SetCreatorProperty(DOCUMENT_CREATOR);
          return pkg;
       }
       catch (Exception e)
       {
           throw new POIXMLException(e);
       }
  }

and using the 'MACRO_DOCUMENT'

public class XWPFRelation : POIXMLRelation {

    /**
     * A map to lookup POIXMLRelation by its relation type
     */
    private static Dictionary<String, XWPFRelation> _table = new Dictionary<String, XWPFRelation>();


    public static XWPFRelation DOCUMENT = new XWPFRelation(
            "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml",
        "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
        "/word/document.xml",
            null
    );
    public static XWPFRelation TEMPLATE = new XWPFRelation(
          "application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml",
      "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
      "/word/document.xml",
          null
    );
    public static XWPFRelation MACRO_DOCUMENT = new XWPFRelation(
            "application/vnd.ms-word.document.macroEnabled.main+xml",
        "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
        "/word/document.xml",
            null
    );

zhuweid avatar Jan 11 '24 01:01 zhuweid

PR is welcomed

tonyqus avatar Apr 27 '24 05:04 tonyqus