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

Support DOCM file type #1250

Open
1 of 5 tasks
TomLingWu opened this issue Jan 11, 2024 · 2 comments
Open
1 of 5 tasks

Support DOCM file type #1250

TomLingWu opened this issue Jan 11, 2024 · 2 comments

Comments

@TomLingWu
Copy link

TomLingWu commented Jan 11, 2024

NPOI Version Used

Version 2.6.2

File Type

  • XLSX
  • XLS
  • 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");
    }
}

@zhuweid
Copy link

zhuweid commented Jan 11, 2024

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
    );

@tonyqus tonyqus added this to the NPOI vNext milestone Jan 19, 2024
@tonyqus tonyqus added the docx label Feb 9, 2024
@tonyqus
Copy link
Member

tonyqus commented Apr 27, 2024

PR is welcomed

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