diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..a377943b --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +*.cs -text +*.vb -text \ No newline at end of file diff --git a/.github/workflows/auto-publish.yml b/.github/workflows/auto-publish.yml new file mode 100644 index 00000000..aae337b6 --- /dev/null +++ b/.github/workflows/auto-publish.yml @@ -0,0 +1,38 @@ +name: auto-publish +run-name: Automatically publish documentation +on: + schedule: + - cron: '45 23 * * WED' +jobs: + auto-publish: + runs-on: ubuntu-latest + permissions: + contents: write + defaults: + run: + shell: bash + working-directory: ./ + steps: + - name: Check out repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Check out main + run: | + echo "Checking out main branch" + git config user.name github-actions + git config user.email github-actions@github.com + git checkout main + - name: Check out live + run: | + echo "Checking out live branch" + git checkout live + - name: Merge from main into live + run: | + echo "Merging from main to live" + git merge main + - name: Push changes + run: | + echo "Pushing changes to live branch" + git push origin live + diff --git a/.github/workflows/samples.yml b/.github/workflows/samples.yml new file mode 100644 index 00000000..62a02fb7 --- /dev/null +++ b/.github/workflows/samples.yml @@ -0,0 +1,21 @@ +name: Samples compilation + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Setup .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: 8.x + - name: Build + run: dotnet build samples/samples.sln /p:TreatWarningsAsErrors=true diff --git a/.gitignore b/.gitignore index 940794e6..f14cbd54 100644 --- a/.gitignore +++ b/.gitignore @@ -286,3 +286,7 @@ __pycache__/ *.btm.cs *.odx.cs *.xsd.cs + +docs/open-xml-docs/ +samples/**/Properties/**/* +samples/**/My\ Project/**/* diff --git a/.openpublishing.publish.config.json b/.openpublishing.publish.config.json index 5e32ffad..e83d1548 100644 --- a/.openpublishing.publish.config.json +++ b/.openpublishing.publish.config.json @@ -6,13 +6,42 @@ "build_output_subfolder": "open-xml-docs", "locale": "en-us", "monikers": [], - "moniker_ranges": [], + "moniker_ranges": [ + "openxml-2.7.1", + "openxml-2.7.2", + "openxml-2.8.0", + "openxml-2.8.1", + "openxml-2.9.0", + "openxml-2.9.1", + "openxml-2.10.0", + "openxml-2.10.1", + "openxml-2.11.0", + "openxml-2.11.1", + "openxml-2.11.2", + "openxml-2.11.3", + "openxml-2.12.0", + "openxml-2.12.1", + "openxml-2.12.2", + "openxml-2.12.3", + "openxml-2.13.0", + "openxml-2.13.1", + "openxml-2.14.0", + "openxml-2.15.0", + "openxml-2.16.0", + "openxml-2.17.1", + "openxml-2.18.0", + "openxml-2.19.0", + "openxml-2.20.0", + "openxml-3.0.0", + "openxml-3.0.1" + ], "open_to_public_contributors": true, "customized_tasks": { "docset_prebuild": [ "_dependentPackages/CommonPlugins/tools/JoinTOC.ps1" ] }, + "xref_query_tags": [ "/dotnet" ], "type_mapping": { "Conceptual": "Content", "ManagedReference": "Content", diff --git a/LICENSE b/LICENSE index 4b1ad51b..21071075 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,21 @@ - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE + MIT License + + Copyright (c) Microsoft Corporation. All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE diff --git a/README.md b/README.md index b61851c0..99cfe893 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Open XML documentation -This repo is the source markdown for documentation published at /office/open-xml/open-xml-sdk.md. +This repo is the source markdown for documentation published at /office/open-xml/open-xml-sdk. ## Contributing diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..e138ec5d --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,41 @@ + + +## Security + +Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). + +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. + +## Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). + +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). + +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). + +Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: + + * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) + * Full paths of source file(s) related to the manifestation of the issue + * The location of the affected source code (tag/branch/commit or direct URL) + * Any special configuration required to reproduce the issue + * Step-by-step instructions to reproduce the issue + * Proof-of-concept or exploit code (if possible) + * Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. + +## Preferred Languages + +We prefer all communications to be in English. + +## Policy + +Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). + + diff --git a/docs/about-the-open-xml-sdk.md b/docs/about-the-open-xml-sdk.md index 90b330d7..6ab0ad18 100644 --- a/docs/about-the-open-xml-sdk.md +++ b/docs/about-the-open-xml-sdk.md @@ -4,7 +4,7 @@ api_name: api_type: - schema ms.assetid: 620e86b5-49f2-43dc-85d4-9c7456c09552 -title: About the Open XML SDK 2.5 for Office +title: About the Open XML SDK for Office ms.suite: office ms.author: o365devx author: o365devx @@ -13,7 +13,7 @@ ms.date: 11/01/2017 ms.localizationpriority: high --- -# About the Open XML SDK 2.5 for Office +# About the Open XML SDK for Office Open XML is an open standard for word-processing documents, presentations, and spreadsheets that can be freely implemented by multiple applications on different platforms. Open XML is designed to faithfully represent existing word-processing documents, presentations, and spreadsheets that are encoded in binary formats defined by Microsoft Office applications. The reason for Open XML is simple: billions of documents now exist but, unfortunately, the information in those documents is tightly coupled with the programs that created them. The purpose of the Open XML standard is to de-couple documents created by Microsoft Office applications so that they can be manipulated by other applications independent of proprietary formats and without the loss of data. @@ -27,7 +27,7 @@ The document parts in an Open XML package are created as XML markup. Because XML Structurally, an Open XML document is an Open Packaging Conventions (OPC) package. As stated previously, a package is composed of a collection of document parts. Each part has a part name that consists of a sequence of segments or a pathname such as "/word/theme/theme1.xml." The package contains a [Content\_Types].xml part that allows you to determine the content type of all document parts in the package. A set of explicit relationships for a source package or part is contained in a relationships part that ends with the .rels extension. -Word processing documents are described by using WordprocessingML markup. For more information, see [Working with WordprocessingML documents (Open XML SDK)](working-with-wordprocessingml-documents.md). A WordprocessingML document is composed of a collection of stories where each story is one of the following: +Word processing documents are described by using WordprocessingML markup. For more information, see [Working with WordprocessingML documents](word/overview.md). A WordprocessingML document is composed of a collection of stories where each story is one of the following: - Main document (the only required story) - Glossary document @@ -36,7 +36,7 @@ Word processing documents are described by using WordprocessingML markup. For mo - Text box - Footnote and endnote -Presentations are described by using PresentationML markup. For more information, see [Working with PresentationML documents (Open XML SDK)](working-with-presentationml-documents.md). Presentation packages can contain the following document parts: +Presentations are described by using PresentationML markup. For more information, see [Working with PresentationML documents](presentation/overview.md). Presentation packages can contain the following document parts: - Slide master - Notes master @@ -44,7 +44,7 @@ Presentations are described by using PresentationML markup. For more information - Slide layout - Notes -Spreadsheet workbooks are described by using SpreadsheetML markup. For more information, see [Working with SpreadsheetML documents (Open XML SDK)](working-with-spreadsheetml-documents.md). Workbook packages can contain: +Spreadsheet workbooks are described by using SpreadsheetML markup. For more information, see [Working with SpreadsheetML documents](spreadsheet/overview.md). Workbook packages can contain: - Workbook part (required part) - One or more worksheets @@ -52,34 +52,22 @@ Spreadsheet workbooks are described by using SpreadsheetML markup. For more info - Tables - Custom XML -## Open XML SDK 1.0 - -Version 1 of the Open XML SDK simplified the manipulation of Open XML packages. The Open XML SDK Application Programming Interface (API) encapsulates many of the common tasks that you typically perform on Open XML packages, so you can perform complex operations with just a few lines of code. Some common tasks: - -- **Search** With a few lines of code, you can search a collection of Excel 2007 worksheets for some arbitrary data. -- **Document assembly** You can create documents by combining the document parts of existing documents programmatically. For example, you can pull slides from various PowerPoint 2007 presentations to create a single presentation. -- **Validation** With a few lines of code, you can validate the document parts in a package or validate an entire package against a schema. -- **Data update** With the Open XML object model, you can easily modify the data in multiple packages. -- **Privacy** With a few lines of code, you can remove comments and other personal information from a document before it is distributed. - -## Open XML SDK 2.0 for Microsoft Office - -The Open XML SDK 2.0 for Microsoft Office extended the strongly typed class support from the part classes, which are provided in version 1.0, to the XML content in each part. All functions available in version 1.0 are still supported. With version 2.0, you are able to program against the XML content inside the part. The SDK supports programming in the style of LINQ to XML which makes coding against the XML content much easier than the traditional W3C XML DOM programming model. +## Open XML SDK for Microsoft Office The SDK supports the following common tasks/scenarios: - **Strongly Typed Classes and Objects** Instead of relying on generic XML functionality to manipulate XML, which requires that you be aware of element/attribute/value spelling as well as namespaces, you can use the Open XML SDK to accomplish the same solution simply by manipulating objects that represent elements/attributes/values. All schema types are represented as strongly typed Common Language Runtime (CLR) classes and all attribute values as enumerations. - **Content Construction, Search, and Manipulation** The LINQ technology is built directly into the SDK. As a result, you are able to perform functional constructs and lambda expression queries directly on objects representing Open XML elements. In addition, the SDK allows you to easily traverse and manipulate content by providing support for collections of objects, like tables and paragraphs. -- **Validation** The Open XML SDK 2.0 for Microsoft Office provides validation functionality, enabling you to validate Open XML documents against different variations of the Open XML Format. +- **Validation** The Open XML SDK for Microsoft Office provides validation functionality, enabling you to validate Open XML documents against different variations of the Open XML Format. -## Open XML SDK 2.5 for Office +## Open XML SDK for Office -The Open XML SDK 2.5 provides the namespaces and members to support the Microsoft Office 2013. The Open XML SDK 2.5 can also read ISO/IEC 29500 Strict Format files. The Strict format is a subset of the Transitional format that does not include legacy features - this makes it theoretically easier for a new implementer to support since it has a smaller technical footprint. +The Open XML SDK provides the namespaces and members to support the Microsoft Office. The Open XML SDK can also read ISO/IEC 29500 Strict Format files. The Strict format is a subset of the Transitional format that does not include legacy features - this makes it theoretically easier for a new implementer to support since it has a smaller technical footprint. The SDK supports the following common tasks/scenarios: -- **Support of Office 2013 Preview file format** In addition to the Open XML SDK 2.0 for Microsoft Office classes, Open XML SDK 2.5 provides new classes that enable you to write and build applications to manipulate Open XML file extensions of the new Office 2013 features. -- **Reads ISO Strict Document File** Open XML SDK 2.5 can read ISO/IEC 29500 Strict Format files. When the Open XML SDK 2.5 API opens a Strict Format file, each Open XML part in the file is loaded to an **OpenXmlPart** class of the Open XML SDK 2.5 by mapping `https://purl.oclc.org/ooxml/` namespaces to the corresponding `https://schemas.openxmlformats.org/` namespaces. -- **Fixes to the Open XML SDK 2.0 for Microsoft Office** Open XML SDK 2.5 includes fixes to known issues in the Open XML SDK 2.0 for Microsoft Office. These include lost whitespaces in PowerPoint presentations and an issue with the Custom UI in Word documents where a specified argument was reported as being out of the range of valid values. +- **Support of Office Preview file format** In addition to the Open XML SDK for Microsoft Office classes, Open XML SDK provides new classes that enable you to write and build applications to manipulate Open XML file extensions of the new Office features. +- **Reads ISO Strict Document File** Open XML SDK can read ISO/IEC 29500 Strict Format files. When the Open XML SDK API opens a Strict Format file, each Open XML part in the file is loaded to an **OpenXmlPart** class of the Open XML SDK by mapping `https://purl.oclc.org/ooxml/` namespaces to the corresponding `https://schemas.openxmlformats.org/` namespaces. +- **Fixes to the Open XML SDK for Microsoft Office** Open XML SDK includes fixes to known issues in the Open XML SDK for Microsoft Office. These include lost whitespaces in PowerPoint presentations and an issue with the Custom UI in Word documents where a specified argument was reported as being out of the range of valid values. -For more information about these and other new features of the Open XML SDK 2.5, see [What's new in the Open XML SDK 2.5 for Office](what-s-new-in-the-open-xml-sdk.md). +For more information about these and other new features of the Open XML SDK, see [What's new in the Open XML SDK for Office](what-s-new-in-the-open-xml-sdk.md). diff --git a/docs/docfx.json b/docs/docfx.json index 7d5e9be1..14da17ef 100644 --- a/docs/docfx.json +++ b/docs/docfx.json @@ -32,6 +32,8 @@ "overwrite": [], "externalReference": [], "globalMetadata": { + "ms.subservice": "open-xml", + "ms.service": "office", "breadcrumb_path": "/office/open-xml/breadcrumb/toc.json", "extendBreadcrumb": true, "uhfHeaderId": "MSDocsHeader-Dev_Office", @@ -39,8 +41,6 @@ "ms.author": "o365devx", "author": "o365devx", "ms.topic": "conceptual", - "ms.prod": "office", - "ms.technology": "open-xml", "description": "Use the Open XML SDK to programmatically create Office Word, Excel, and PowerPoint documents, and manipulate their content." }, "fileMetadata": { @@ -48,7 +48,10 @@ "**/*.yml": ["csharp", "vb"] } }, - "template": [], + "template": [ + "default", + "modern" + ], "dest": "open-xml-docs", "markdownEngineName": "markdig" } diff --git a/docs/general/diagnosticids.md b/docs/general/diagnosticids.md new file mode 100644 index 00000000..5094d5eb --- /dev/null +++ b/docs/general/diagnosticids.md @@ -0,0 +1,59 @@ +--- +title: Diagnostic IDs +ms.suite: office + +ms.author: o365devx +author: o365devx +ms.topic: conceptual +ms.date: 01/08/2025 +ms.localizationpriority: high +--- + +# Diagnostic IDs + +Diagnostic IDs are used to identify APIs or patterns that can raise compiler warnings or errors. This can be done via or . These can be suppressed at the consumer level for each diagnostic id. + +## Experimental APIs + +### OOXML0001 + +**Title**: IPackage related APIs are currently experimental + +As of v3.0, a new abstraction layer was added in between `System.IO.Packaging` and `DocumentFormat.OpenXml.Packaging.OpenXmlPackage`. This is currently experimental, but can be used if needed. This will be stabilized in a future release, and may or may not require code changes. + +## Suppress warnings + +It's recommended that you use an available workaround whenever possible. However, if you cannot change your code, you can suppress warnings through a `#pragma` directive or a `` project setting. If you must use the obsolete or experimental APIs and the `OOXMLXXXX` diagnostic does not surface as an error, you can suppress the warning in code or in your project file. + +To suppress the warnings in code: + +```csharp +// Disable the warning. +#pragma warning disable OOXML0001 + +// Code that uses obsolete or experimental API. +//... + +// Re-enable the warning. +#pragma warning restore OOXML0001 +``` + +To suppress the warnings in a project file: + +```xml + + + net6.0 + + $(NoWarn);OOXML0001 + + $(NoWarn);OOXML0001 + $(NoWarn);OTHER_WARNING + + $(NoWarn);OOXML0001;OTHER_WARNING + + +``` + +> [!NOTE] +> Suppressing warnings in this way only disables the obsoletion warnings you specify. It doesn't disable any other warnings, including obsoletion warnings with different diagnostic IDs. diff --git a/docs/general/features.md b/docs/general/features.md new file mode 100644 index 00000000..6c3587cd --- /dev/null +++ b/docs/general/features.md @@ -0,0 +1,162 @@ +--- +title: Custom SDK Features +ms.suite: office + +ms.author: o365devx +author: o365devx +ms.topic: conceptual +ms.date: 11/13/2023 +ms.localizationpriority: medium +--- + +# Custom SDK Features + +Features in the Open XML SDK are available starting in v2.14.0 that allows for behavior and state to be contained within the document or part and customized without reimplementing the containing package or part. This is accessed via `Features` property on packages, parts, and elements. + +This is an implementation of the [strategy pattern](https://refactoring.guru/design-patterns/strategy) that makes it easy to replace behavior on the fly. It is modeled after the [request features](/aspnet/core/fundamentals/request-features) in ASP.NET Core. + +## Feature inheritance + +Packages, parts, and elements all have their own feature collection. However, they will also inherit the containing part and package if it is available. + +To highlight this, see the test case below: + +```csharp +OpenXmlPackage package = /* Create a package */; + +var packageFeature = new PrivateFeature(); +package.Features.Set(packageFeature); + +var part = package.GetPartById("existingPart"); +Assert.Same(part.Features.GetRequired(), package.Features.GetRequired()); + +part.Features.Set(new()); +Assert.NotSame(part.Features.GetRequired(), package.Features.GetRequired()); + + +private sealed class PrivateFeature +{ +} +``` + +> [!NOTE] +> The feature collection on elements is readonly. This is due to memory issues if it is made writeable. If this is needed, please engage on https://github.com/dotnet/open-xml-sdk to let us know your scenario. + +## Visualizing Registered Features + +The in-box implementations of the provide a helpful debug view so you can see what features are available and what their properties/fields are: + +![Features Debug View](../media/feature-debug-view.png) + +## Available Features + +The features that are currently available are described below and at what scope they are available: + +### + +This feature allows for registering actions that need to run when a package or a part is destroyed or disposed: + +```csharp +OpenXmlPackage package = GetSomePackage(); +package.Features.Get().Register(() => /* Some action that is called when the package is disposed */); + +OpenXmlPart part = GetSomePart(); +part.Features.Get().Register(() => /* Some action that is called when the part is removed or closed */); +``` + +Packages and parts will have their own implementations of this feature. Elements will retrieve the feature for their containing part if available. + +### + +This feature allows getting event notifications of when a package is changed: + +```csharp +OpenXmlPackage package = GetSomePackage(); +package.TryAddPackageEventsFeature(); + +var feature = package.Features.GetRequired(); +``` + +> [!NOTE] +> There may be times when the package is changed but an event is not fired. Not all areas have been identified where it would make sense to raise an event. Please file an issue if you find one. + +### + +This feature allows getting event notifications of when an event is being created. This is a feature that is added to the part or package: + +```csharp +OpenXmlPart part = GetSomePackage(); +package.AddPartEventsFeature(); + +var feature = part.Features.GetRequired(); +``` + +Generally, assume that there may be a singleton implementation for the events and verify that the part is the correct part. + +> [!NOTE] +> There may be times when the part is changed but an event is not fired. Not all areas have been identified where it would make sense to raise an event. Please file an issue if you find one. + +### + +This feature allows getting event notifications of when a part root is being modified/loaded/created/etc. This is a feature that is added to the part level feature: + +```csharp +OpenXmlPart part = GetSomePart(); +part.AddPartRootEventsFeature(); + +var feature = part.Features.GetRequired(); +``` + +Generally, assume that there may be a singleton implementation for the events and verify that the part is the correct part. + +> [!NOTE] +> There may be times when the part root is changed but an event is not fired. Not all areas have been identified where it would make sense to raise an event. Please file an issue if you find one. + +### + +This feature allows for a shared service to generate random numbers and fill an array. + +### + +This feature allows for population and tracking of elements that contain paragraph ids. By default, this will ensure uniqueness of values and ensure that values that do exist are valid per the constraints of the standard. To use this feature: + +```csharp +WordprocessingDocument document = CreateWordDocument(); +document.TryAddParagraphIdFeature(); + +var part = doc.AddMainDocumentPart(); +var body = new Body(); +part.Document = new Document(body); + +var p = new Paragraph(); +body.AddChild(p); // After adding p.ParagraphId will be set to a unique, valid value +``` + +This feature can also be used to ensure uniqueness among multiple documents with a slight change: + +```csharp +using var doc1 = CreateDocument1(); +using var doc2 = CreateDocument2(); + +var shared = doc1 + .AddSharedParagraphIdFeature() + .Add(doc2); + +// Add item to doc1 +var part1 = doc1.AddMainDocumentPart(); +var body1 = new Body(); +var p1 = new Paragraph(); +part1.Document = new Document(body1); +body1.AddChild(p1); + +// Add item with same ID to doc2 +var part2 = doc2.AddMainDocumentPart(); +var body2 = new Body(); +var p2 = new Paragraph { ParagraphId = p1.ParagraphId }; +part2.Document = new Document(body2); +body2.AddChild(p2); + +// Assert +Assert.NotEqual(p1.ParagraphId, p2.ParagraphId); +Assert.Equal(2, shared.Count); +``` diff --git a/docs/general/how-to-add-a-new-document-part-that-receives-a-relationship-id-to-a-package.md b/docs/general/how-to-add-a-new-document-part-that-receives-a-relationship-id-to-a-package.md new file mode 100644 index 00000000..296f5d06 --- /dev/null +++ b/docs/general/how-to-add-a-new-document-part-that-receives-a-relationship-id-to-a-package.md @@ -0,0 +1,82 @@ +--- + +api_name: +- Microsoft.Office.DocumentFormat.OpenXML.Packaging +api_type: +- schema +ms.assetid: c9b2ce55-548c-4443-8d2e-08fe1f06b7d7 +title: 'How to: Add a new document part that receives a relationship ID to a package' +ms.suite: office + +ms.author: o365devx +author: o365devx +ms.topic: conceptual +ms.date: 01/08/2025 +ms.localizationpriority: medium +--- + +# Add a new document part that receives a relationship ID to a package + +This topic shows how to use the classes in the Open XML SDK for +Office to add a document part (file) that receives a relationship `Id` parameter for a word +processing document. + + + +----------------------------------------------------------------------------- +[!include[Structure](../includes/word/packages-and-document-parts.md)] + + +----------------------------------------------------------------------------- + +[!include[Structure](../includes/word/structure.md)] + +----------------------------------------------------------------------------- + +## How the Sample Code Works + +The sample code, in this how-to, starts by passing in a parameter that represents the path to the Word document. It then creates +a new WordprocessingDocument object within a using statement. + +### [C#](#tab/cs-1) +[!code-csharp[](../../samples/word/add_a_new_part_that_receives_a_relationship_id_to_a_package/cs/Program.cs#snippet1)] + +### [Visual Basic](#tab/vb-1) +[!code-vb[](../../samples/word/add_a_new_part_that_receives_a_relationship_id_to_a_package/vb/Program.vb#snippet1)] +*** + +It then adds the MainDocumentPart part in the new word processing document, with the relationship ID, rId1. It also adds the `CustomFilePropertiesPart` part and a `CoreFilePropertiesPart` in the new word processing document. + +### [C#](#tab/cs-2) +[!code-csharp[](../../samples/word/add_a_new_part_that_receives_a_relationship_id_to_a_package/cs/Program.cs#snippet2)] + +### [Visual Basic](#tab/vb-2) +[!code-vb[](../../samples/word/add_a_new_part_that_receives_a_relationship_id_to_a_package/vb/Program.vb#snippet2)] +*** + +The code then adds the `DigitalSignatureOriginPart` part, the `ExtendedFilePropertiesPart` part, and the `ThumbnailPart` part in the new word processing document with realtionship IDs rId4, rId5, and rId6. + +> [!NOTE] +> The method creates a relationship from the current document part to the new document part. This method returns the new document part. Also, you can use the method to fill the document part. + +## Sample Code + +The following code, adds a new document part that contains custom XML +from an external file and then populates the document part. Below is the +complete code example in both C\# and Visual Basic. + +### [C#](#tab/cs) +[!code-csharp[](../../samples/word/add_a_new_part_that_receives_a_relationship_id_to_a_package/cs/Program.cs#snippet0)] + +### [Visual Basic](#tab/vb) +[!code-vb[](../../samples/word/add_a_new_part_that_receives_a_relationship_id_to_a_package/vb/Program.vb#snippet0)] +*** + +----------------------------------------------------------------------------- +## See also + + +- [Open XML SDK class library reference](/office/open-xml/open-xml-sdk) + + + diff --git a/docs/general/how-to-add-a-new-document-part-to-a-package.md b/docs/general/how-to-add-a-new-document-part-to-a-package.md new file mode 100644 index 00000000..5cc51b22 --- /dev/null +++ b/docs/general/how-to-add-a-new-document-part-to-a-package.md @@ -0,0 +1,80 @@ +--- +api_name: +- Microsoft.Office.DocumentFormat.OpenXML.Packaging +api_type: +- schema +ms.assetid: ec83a076-9d71-49d1-915f-e7090f74c13a +title: 'How to: Add a new document part to a package' +ms.suite: office +ms.author: o365devx +author: o365devx +ms.topic: conceptual +ms.date: 01/08/2025 +ms.localizationpriority: medium +--- + +# Add a new document part to a package + +This topic shows how to use the classes in the Open XML SDK for Office to add a document part (file) to a word processing document programmatically. + +[!include[Structure](../includes/word/packages-and-document-parts.md)] + +## Get a WordprocessingDocument object + +The code starts with opening a package file by passing a file name to one of the overloaded methods of the that takes a string and a Boolean value that specifies whether the file should be opened for editing or for read-only access. In this case, the Boolean value is `true` specifying that the file should be opened in read/write mode. + +### [C#](#tab/cs-1) +[!code-csharp[](../../samples/word/add_a_new_part_to_a_package/cs/Program.cs#snippet1)] + +### [Visual Basic](#tab/vb-1) +[!code-vb[](../../samples/word/add_a_new_part_to_a_package/vb/Program.vb#snippet1)] +*** + + +[!include[Using Statement](../includes/word/using-statement.md)] + +[!include[Structure](../includes/word/structure.md)] + +## How the sample code works + +After opening the document for editing, in the `using` statement, as a object, the code creates a reference to the `MainDocumentPart` part and adds a new custom XML part. It then reads the contents of the external +file that contains the custom XML and writes it to the `CustomXmlPart` part. + +> [!NOTE] +> To use the new document part in the document, add a link to the document part in the relationship part for the new part. + +### [C#](#tab/cs-2) +[!code-csharp[](../../samples/word/add_a_new_part_to_a_package/cs/Program.cs#snippet2)] + +### [Visual Basic](#tab/vb-2) +[!code-vb[](../../samples/word/add_a_new_part_to_a_package/vb/Program.vb#snippet2)] +*** + + +## Sample code + +The following code adds a new document part that contains custom XML from an external file and then populates the part. To call the `AddCustomXmlPart` method in your program, use the following example that modifies a file by adding a new document part to it. + +### [C#](#tab/cs-3) +[!code-csharp[](../../samples/word/add_a_new_part_to_a_package/cs/Program.cs#snippet3)] + +### [Visual Basic](#tab/vb-3) +[!code-vb[](../../samples/word/add_a_new_part_to_a_package/vb/Program.vb#snippet3)] +*** + + +> [!NOTE] +> Before you run the program, change the Word file extension from .docx to .zip, and view the content of the zip file. Then change the extension back to .docx and run the program. After running the program, change the file extension again to .zip and view its content. You will see an extra folder named "customXML." This folder contains the XML file that represents the added part + +Following is the complete code example in both C\# and Visual Basic. + +### [C#](#tab/cs) +[!code-csharp[](../../samples/word/add_a_new_part_to_a_package/cs/Program.cs#snippet0)] + +### [Visual Basic](#tab/vb) +[!code-vb[](../../samples/word/add_a_new_part_to_a_package/vb/Program.vb#snippet0)] +*** + +## See also + +- [Open XML SDK class library reference](/office/open-xml/open-xml-sdk) diff --git a/docs/general/how-to-copy-the-contents-of-an-open-xml-package-part-to-a-document-part-in-a-dif.md b/docs/general/how-to-copy-the-contents-of-an-open-xml-package-part-to-a-document-part-in-a-dif.md new file mode 100644 index 00000000..5125daf0 --- /dev/null +++ b/docs/general/how-to-copy-the-contents-of-an-open-xml-package-part-to-a-document-part-in-a-dif.md @@ -0,0 +1,157 @@ +--- + +api_name: +- Microsoft.Office.DocumentFormat.OpenXML.Packaging +api_type: +- schema +ms.assetid: 7dbfd93c-a9e3-4465-9b57-4a043b07b807 +title: 'Copy contents of an Open XML package part to a document part in a different package' +ms.suite: office + +ms.author: o365devx +author: o365devx +ms.topic: conceptual +ms.date: 01/08/2025 +ms.localizationpriority: medium +--- + +# Copy contents of an Open XML package part to a document part in a different package + +This topic shows how to use the classes in the Open XML SDK for +Office to copy the contents of an Open XML Wordprocessing document part +to a document part in a different word-processing document +programmatically. + + + +-------------------------------------------------------------------------------- +[!include[Structure](../includes/word/packages-and-document-parts.md)] + + +-------------------------------------------------------------------------------- +## Getting a WordprocessingDocument Object + +To open an existing document, instantiate the class as shown in +the following two `using` statements. In the +same statement, you open the word processing file with the specified +file name by using the method, with the Boolean parameter. +For the source file that set the parameter to `false` to open it for read-only access. For the +target file, set the parameter to `true` in +order to enable editing the document. + +### [C#](#tab/cs-1) +[!code-csharp[](../../samples/word/copy_the_contents_of_an_open_xml_package_part_to_a_part_a_dif/cs/Program.cs#snippet1)] + +### [Visual Basic](#tab/vb-1) +[!code-vb[](../../samples/word/copy_the_contents_of_an_open_xml_package_part_to_a_part_a_dif/vb/Program.vb#snippet1)] +*** + +[!include[Using Statement](../includes/word/using-statement.md)] + +-------------------------------------------------------------------------------- + +[!include[Structure](../includes/word/structure.md)] + +-------------------------------------------------------------------------------- +## The Theme Part + +The theme part contains information about the color, font, and format of +a document. It is defined in the [!include[ISO/IEC 29500 URL](../includes/iso-iec-29500-link.md)] specification as +follows. + +An instance of this part type contains information about a document's +theme, which is a combination of color scheme, font scheme, and format +scheme (the latter also being referred to as effects). For a +WordprocessingML document, the choice of theme affects the color and +style of headings, among other things. For a SpreadsheetML document, the +choice of theme affects the color and style of cell contents and charts, +among other things. For a PresentationML document, the choice of theme +affects the formatting of slides, handouts, and notes via the associated +master, among other things. + +A WordprocessingML or SpreadsheetML package shall contain zero or one +Theme part, which shall be the target of an implicit relationship in a +Main Document (§11.3.10) or Workbook (§12.3.23) part. A PresentationML +package shall contain zero or one Theme part per Handout Master +(§13.3.3), Notes Master (§13.3.4), Slide Master (§13.3.10) or +Presentation (§13.3.6) part via an implicit relationship. + +*Example*: The following WordprocessingML Main Document +part-relationship item contains a relationship to the Theme part, which +is stored in the ZIP item theme/theme1.xml: + +```xml + + + +``` + + +© [!include[ISO/IEC 29500 version](../includes/iso-iec-29500-version.md)] + + +-------------------------------------------------------------------------------- +## How the Sample Code Works + +To copy the contents of a document part in an Open XML package to a +document part in a different package, the full path of the each word +processing document is passed in as a parameter to the `CopyThemeContent` method. The code then opens both +documents as +objects, and creates variables that reference the parts in each of the packages. + +### [C#](#tab/cs-2) +[!code-csharp[](../../samples/word/copy_the_contents_of_an_open_xml_package_part_to_a_part_a_dif/cs/Program.cs#snippet2)] + +### [Visual Basic](#tab/vb-2) +[!code-vb[](../../samples/word/copy_the_contents_of_an_open_xml_package_part_to_a_part_a_dif/vb/Program.vb#snippet2)] +*** + + +The code then reads the contents of the source part by using a `StreamReader` object and writes to the target + part by using a . + +### [C#](#tab/cs-3) +[!code-csharp[](../../samples/word/copy_the_contents_of_an_open_xml_package_part_to_a_part_a_dif/cs/Program.cs#snippet3)] + +### [Visual Basic](#tab/vb-3) +[!code-vb[](../../samples/word/copy_the_contents_of_an_open_xml_package_part_to_a_part_a_dif/vb/Program.vb#snippet3)] +*** + + +-------------------------------------------------------------------------------- +## Sample Code + +The following code copies the contents of one document part in an Open +XML package to a document part in a different package. To call the `CopyThemeContent` method, you can use the +following example, which copies the theme part from the packages located at `args[0]` to +one located at `args[1]`. + +### [C#](#tab/cs-4) +[!code-csharp[](../../samples/word/copy_the_contents_of_an_open_xml_package_part_to_a_part_a_dif/cs/Program.cs#snippet4)] + +### [Visual Basic](#tab/vb-4) +[!code-vb[](../../samples/word/copy_the_contents_of_an_open_xml_package_part_to_a_part_a_dif/vb/Program.vb#snippet4)] +*** + + +> [!IMPORTANT] +> Before you run the program, make sure that the source document has the theme part set. To add a theme to a document, +> open it in Microsoft Word, click the **Design** tab then click **Themes**, and select one of the available themes. + +After running the program, you can inspect the file to see +the changed theme. + +Following is the complete sample code in both C\# and Visual Basic. + +### [C#](#tab/cs) +[!code-csharp[](../../samples/word/copy_the_contents_of_an_open_xml_package_part_to_a_part_a_dif/cs/Program.cs#snippet0)] + +### [Visual Basic](#tab/vb) +[!code-vb[](../../samples/word/copy_the_contents_of_an_open_xml_package_part_to_a_part_a_dif/vb/Program.vb#snippet0)] +*** + +-------------------------------------------------------------------------------- +## See also + +- [Open XML SDK class library reference](/office/open-xml/open-xml-sdk) diff --git a/docs/general/how-to-create-a-package.md b/docs/general/how-to-create-a-package.md new file mode 100644 index 00000000..2d26e059 --- /dev/null +++ b/docs/general/how-to-create-a-package.md @@ -0,0 +1,82 @@ +--- + +api_name: +- Microsoft.Office.DocumentFormat.OpenXML.Packaging +api_type: +- schema +ms.assetid: fe261589-7b04-47df-8ee9-26b444e587b0 +title: 'How to: Create a package' +ms.suite: office + +ms.author: o365devx +author: o365devx +ms.topic: conceptual +ms.date: 01/03/2025 +ms.localizationpriority: medium +--- + +# Create a package + +This topic shows how to use the classes in the Open XML SDK for +Office to programmatically create a word processing document package +from content in the form of `WordprocessingML` XML markup. + +[!include[Structure](../includes/word/packages-and-document-parts.md)] + +## Getting a WordprocessingDocument Object + +In the Open XML SDK, the class represents a Word document package. To create a Word document, you create an instance +of the class and +populate it with parts. At a minimum, the document must have a main +document part that serves as a container for the main text of the +document. The text is represented in the package as XML using `WordprocessingML` markup. + +To create the class instance you call . Several methods are +provided, each with a different signature. The first parameter takes a full path +string that represents the document that you want to create. The second +parameter is a member of the enumeration. +This parameter represents the type of document. For example, there is a +different member of the enumeration for each +of document, template, and the macro enabled variety of document and +template. + +> [!NOTE] +> Carefully select the appropriate and verify that the persisted file has the correct, matching file extension. If the does not match the file extension, an error occurs when you open the file in Microsoft Word. + +### [C#](#tab/cs-1) +[!code-csharp[](../../samples/word/create_a_package/cs/Program.cs#snippet1)] + +### [Visual Basic](#tab/vb-1) +[!code-vb[](../../samples/word/create_a_package/vb/Program.vb#snippet1)] +*** + +[!include[Using Statement](../includes/word/using-statement.md)] + +Once you have created the Word document package, you can add parts to +it. To add the main document part you call . Having done that, +you can set about adding the document structure and text. + +[!include[Structure](../includes/word/structure.md)] + +## Sample Code + +The following is the complete code sample that you can use to create an +Open XML word processing document package from XML content in the form +of `WordprocessingML` markup. + +After you run the program, open the created file and +examine its content; it should be one paragraph that contains the phrase +"Hello world!" + +Following is the complete sample code in both C\# and Visual Basic. + +### [C#](#tab/cs) +[!code-csharp[](../../samples/word/create_a_package/cs/Program.cs#snippet0)] + +### [Visual Basic](#tab/vb) +[!code-vb[](../../samples/word/create_a_package/vb/Program.vb#snippet0)] +*** + +## See also + +- [Open XML SDK class library reference](/office/open-xml/open-xml-sdk) diff --git a/docs/general/how-to-get-the-contents-of-a-document-part-from-a-package.md b/docs/general/how-to-get-the-contents-of-a-document-part-from-a-package.md new file mode 100644 index 00000000..8c1fe0b6 --- /dev/null +++ b/docs/general/how-to-get-the-contents-of-a-document-part-from-a-package.md @@ -0,0 +1,146 @@ +--- + +api_name: +- Microsoft.Office.DocumentFormat.OpenXML.Packaging +api_type: +- schema +ms.assetid: b0d3d890-431a-4838-89dc-1f0dccd5dcd0 +title: 'How to: Get the contents of a document part from a package' +ms.suite: office + +ms.author: o365devx +author: o365devx +ms.topic: conceptual +ms.date: 01/08/2025 +ms.localizationpriority: high +--- +# Get the contents of a document part from a package + +This topic shows how to use the classes in the Open XML SDK for +Office to retrieve the contents of a document part in a Wordprocessing +document programmatically. + + + +-------------------------------------------------------------------------------- +[!include[Structure](../includes/word/packages-and-document-parts.md)] + + +--------------------------------------------------------------------------------- +## Getting a WordprocessingDocument Object + +The code starts with opening a package file by passing a file name to +one of the overloaded methods (Visual Basic .NET Shared +method or C\# static method) of the class that takes a +string and a Boolean value that specifies whether the file should be +opened in read/write mode or not. In this case, the Boolean value is +`false` specifying that the file should be +opened in read-only mode to avoid accidental changes. + +### [C#](#tab/cs-1) +[!code-csharp[](../../samples/word/get_the_contents_of_a_part_from_a_package/cs/Program.cs#snippet1)] + +### [Visual Basic](#tab/vb-1) +[!code-vb[](../../samples/word/get_the_contents_of_a_part_from_a_package/vb/Program.vb#snippet1)] +*** + +[!include[Using Statement](../includes/word/using-statement.md)] + + +--------------------------------------------------------------------------------- + +[!include[Structure](../includes/word/structure.md)] + +-------------------------------------------------------------------------------- +## Comments Element + +In this how-to, you are going to work with comments. Therefore, it is +useful to familiarize yourself with the structure of the `` element. The following information +from the [!include[ISO/IEC 29500 URL](../includes/iso-iec-29500-link.md)] +specification can be useful when working with this element. + +This element specifies all of the comments defined in the current +document. It is the root element of the comments part of a +WordprocessingML document.Consider the following WordprocessingML +fragment for the content of a comments part in a WordprocessingML +document: + +```xml + + + … + + +``` + +The **comments** element contains the single +comment specified by this document in this example. + +© [!include[ISO/IEC 29500 version](../includes/iso-iec-29500-version.md)] + +The following XML schema fragment defines the contents of this element. + +```xml + + + + + +``` + +-------------------------------------------------------------------------------- +## How the Sample Code Works + +After you have opened the source file for reading, you create a `mainPart` object by instantiating the `MainDocumentPart`. Then you can create a reference +to the `WordprocessingCommentsPart` part of +the document. + +### [C#](#tab/cs-2) +[!code-csharp[](../../samples/word/get_the_contents_of_a_part_from_a_package/cs/Program.cs#snippet2)] + +### [Visual Basic](#tab/vb-2) +[!code-vb[](../../samples/word/get_the_contents_of_a_part_from_a_package/vb/Program.vb#snippet2)] +*** + + +You can then use a `StreamReader` object to +read the contents of the `WordprocessingCommentsPart` part of the document +and return its contents. + +### [C#](#tab/cs-3) +[!code-csharp[](../../samples/word/get_the_contents_of_a_part_from_a_package/cs/Program.cs#snippet3)] + +### [Visual Basic](#tab/vb-3) +[!code-vb[](../../samples/word/get_the_contents_of_a_part_from_a_package/vb/Program.vb#snippet3)] +*** + + +-------------------------------------------------------------------------------- +## Sample Code +The following code retrieves the contents of a `WordprocessingCommentsPart` part contained in a +`WordProcessing` document package. You can +run the program by calling the `GetCommentsFromDocument` method as shown in the +following example. + +### [C#](#tab/cs-4) +[!code-csharp[](../../samples/word/get_the_contents_of_a_part_from_a_package/cs/Program.cs#snippet4)] + +### [Visual Basic](#tab/vb-4) +[!code-vb[](../../samples/word/get_the_contents_of_a_part_from_a_package/vb/Program.vb#snippet4)] +*** + +Following is the complete code example in both C\# and Visual Basic. + +### [C#](#tab/cs) +[!code-csharp[](../../samples/word/get_the_contents_of_a_part_from_a_package/cs/Program.cs#snippet0)] + +### [Visual Basic](#tab/vb) +[!code-vb[](../../samples/word/get_the_contents_of_a_part_from_a_package/vb/Program.vb#snippet0)] +*** + +-------------------------------------------------------------------------------- +## See also + + +[Open XML SDK class library +reference](/office/open-xml/open-xml-sdk) diff --git a/docs/general/how-to-remove-a-document-part-from-a-package.md b/docs/general/how-to-remove-a-document-part-from-a-package.md new file mode 100644 index 00000000..8d594ea4 --- /dev/null +++ b/docs/general/how-to-remove-a-document-part-from-a-package.md @@ -0,0 +1,115 @@ +--- + +api_name: +- Microsoft.Office.DocumentFormat.OpenXML.Packaging +api_type: +- schema +ms.assetid: b3890e64-51d1-4643-8d07-2c9d8e060000 +title: 'How to: Remove a document part from a package' +ms.suite: office + +ms.author: o365devx +author: o365devx +ms.topic: conceptual +ms.date: 01/03/2025 +ms.localizationpriority: medium +--- +# Remove a document part from a package + +This topic shows how to use the classes in the Open XML SDK for +Office to remove a document part (file) from a Wordprocessing document +programmatically. + + + +-------------------------------------------------------------------------------- +[!include[Structure](../includes/word/packages-and-document-parts.md)] + + +--------------------------------------------------------------------------------- +## Getting a WordprocessingDocument Object + +The code example starts with opening a package file by passing a file +name as an argument to one of the overloaded methods of the + +that takes a string and a Boolean value that specifies whether the file +should be opened in read/write mode or not. In this case, the Boolean +value is `true` specifying that the file +should be opened in read/write mode. + +### [C#](#tab/cs-1) +[!code-csharp[](../../samples/word/remove_a_part_from_a_package/cs/Program.cs#snippet1)] + +### [Visual Basic](#tab/vb-1) +[!code-vb[](../../samples/word/remove_a_part_from_a_package/vb/Program.vb#snippet1)] +*** + + +[!include[Using Statement](../includes/word/using-statement.md)] + + +--------------------------------------------------------------------------------- + +[!include[Structure](../includes/word/structure.md)] + +-------------------------------------------------------------------------------- +## Settings Element +The following text from the [!include[ISO/IEC 29500 URL](../includes/iso-iec-29500-link.md)] specification +introduces the settings element in a `PresentationML` package. + +> This element specifies the settings that are applied to a +> WordprocessingML document. This element is the root element of the +> Document Settings part in a WordprocessingML document. +> **Example**: +> Consider the following WordprocessingML fragment for the settings part +> of a document: + +```xml + + + + +``` + +> The **settings** element contains all of the +> settings for this document. In this case, the two settings applied are +> automatic tab stop increments of 0.5" using the **defaultTabStop** element, and no character level +> white space compression using the **characterSpacingControl** element. +> +> © [!include[ISO/IEC 29500 version](../includes/iso-iec-29500-version.md)] + + +-------------------------------------------------------------------------------- +## How the Sample Code Works + +After you have opened the document, in the `using` statement, as a object, you create a +reference to the `DocumentSettingsPart` part. +You can then check if that part exists, if so, delete that part from the +package. In this instance, the `settings.xml` +part is removed from the package. + +### [C#](#tab/cs-2) +[!code-csharp[](../../samples/word/remove_a_part_from_a_package/cs/Program.cs#snippet2)] + +### [Visual Basic](#tab/vb-2) +[!code-vb[](../../samples/word/remove_a_part_from_a_package/vb/Program.vb#snippet2)] +*** + + +-------------------------------------------------------------------------------- +## Sample Code + +Following is the complete code example in both C\# and Visual Basic. + +### [C#](#tab/cs) +[!code-csharp[](../../samples/word/remove_a_part_from_a_package/cs/Program.cs#snippet0)] + +### [Visual Basic](#tab/vb) +[!code-vb[](../../samples/word/remove_a_part_from_a_package/vb/Program.vb#snippet0)] +*** + +-------------------------------------------------------------------------------- +## See also + + +- [Open XML SDK class library reference](/office/open-xml/open-xml-sdk) diff --git a/docs/general/how-to-replace-the-theme-part-in-a-word-processing-document.md b/docs/general/how-to-replace-the-theme-part-in-a-word-processing-document.md new file mode 100644 index 00000000..5d1b1527 --- /dev/null +++ b/docs/general/how-to-replace-the-theme-part-in-a-word-processing-document.md @@ -0,0 +1,175 @@ +--- + +api_name: +- Microsoft.Office.DocumentFormat.OpenXML.Packaging +api_type: +- schema +ms.assetid: cfb75725-f3a7-43c0-85f4-7bb4c3f448ca +title: 'How to: Replace the theme part in a word processing document' +ms.suite: office + +ms.author: o365devx +author: o365devx +ms.topic: conceptual +ms.date: 01/08/2025 +ms.localizationpriority: medium +--- +# Replace the theme part in a word processing document + +This topic shows how to use the classes in the Open XML SDK for +Office to programmatically replace a document part in a word processing +document. + +[!include[Structure](../includes/word/packages-and-document-parts.md)] + + +## Getting a WordprocessingDocument Object + +In the sample code, you start by opening the word processing file by +instantiating the class as shown in +the following `using` statement. In the same +statement, you open the word processing file *document* by using the + method, with the Boolean parameter set +to `true` to enable editing the document. + +### [C#](#tab/cs-1) +[!code-csharp[](../../samples/word/replace_the_theme_part/cs/Program.cs#snippet1)] + +### [Visual Basic](#tab/vb-1) +[!code-vb[](../../samples/word/replace_the_theme_part/vb/Program.vb#snippet1)] +*** + +[!include[Using Statement](../includes/word/using-statement.md)] + + +## How to Change Theme in a Word Package + +If you would like to change the theme in a Word document, click the +ribbon **Design** and then click **Themes**. The **Themes** pull-down +menu opens. To choose one of the built-in themes and apply it to the +Word document, click the theme icon. You can also use the option **Browse for Themes...** to locate and apply a theme file +in your computer. + + +## The Structure of the Theme Element + +The theme element is constituted of color, font, and format schemes. In +this how-to you learn how to change the theme programmatically. +Therefore, it is useful to familiarize yourself with the theme element. +The following information from the [!include[ISO/IEC 29500 URL](../includes/iso-iec-29500-link.md)] specification can +be useful when working with this element. + +This element defines the root level complex type associated with a +shared style sheet (or theme). This element holds all the different +formatting options available to a document through a theme, and defines +the overall look and feel of the document when themed objects are used +within the document. + +[*Example*: Consider the following image as an example of different +themes in use applied to a presentation. In this example, you can see +how a theme can affect font, colors, backgrounds, fills, and effects for +different objects in a presentation. end example] + +![Theme sample](../media/a-theme01.gif) + +In this example, we see how a theme can affect font, colors, +backgrounds, fills, and effects for different objects in a presentation. +*end example*] + +© [!include[ISO/IEC 29500 version](../includes/iso-iec-29500-version.md)] + +The following table lists the possible child types of the Theme class. + +| PresentationML Element | Open XML SDK Class | Description | +|---|---|---| +| `` | |Custom Color List | +| `` | | Extension List | +| `` | | Extra Color Scheme List | +| `` | | Object Defaults | +| `` | | Theme Elements | + +The following XML Schema fragment defines the four parts of the theme +element. The `themeElements` element is the +piece that holds the main formatting defined within the theme. The other +parts provide overrides, defaults, and additions to the information +contained in `themeElements`. The complex +type defining a theme, `CT_OfficeStyleSheet`, is defined in the following +manner: + +```xml + + + + + + + + + + +``` + +This complex type also holds a `CT_OfficeArtExtensionList`, which is used for +future extensibility of this complex type. + + +## How the Sample Code Works + +After opening the file, you can instantiate the `MainDocumentPart` in the `wordDoc` object, and +delete the old theme part. + +### [C#](#tab/cs-2) +[!code-csharp[](../../samples/word/replace_the_theme_part/cs/Program.cs#snippet2)] + +### [Visual Basic](#tab/vb-2) +[!code-vb[](../../samples/word/replace_the_theme_part/vb/Program.vb#snippet2)] +*** + +You can then create add a new +object and add it to the `MainDocumentPart` +object. Then you add content by using a `StreamReader` and objects to copy the theme from the +`themeFile` to the object. + +### [C#](#tab/cs-3) +[!code-csharp[](../../samples/word/replace_the_theme_part/cs/Program.cs#snippet3)] + +### [Visual Basic](#tab/vb-3) +[!code-vb[](../../samples/word/replace_the_theme_part/vb/Program.vb#snippet3)] +*** + + +## Sample Code + +The following code example shows how to replace the theme document part +in a word processing document with the theme part from another package. +The theme file passed as the second argument must be a valid theme part +in XML format (for example, Theme1.xml). You can extract this part from +an existing document or theme file (.THMX) that has been renamed to be a +.Zip file. To call the method `ReplaceTheme` +you can use the following call example to copy the theme from the file +from `arg[1]` and to the file located at `arg[0]` + +### [C#](#tab/cs-4) +[!code-csharp[](../../samples/word/replace_the_theme_part/cs/Program.cs#snippet4)] + +### [Visual Basic](#tab/vb-4) +[!code-vb[](../../samples/word/replace_the_theme_part/vb/Program.vb#snippet4)] +*** + + +After you run the program open the Word file and notice the new theme changes. + +Following is the complete sample code in both C\# and Visual Basic. + +### [C#](#tab/cs) +[!code-csharp[](../../samples/word/replace_the_theme_part/cs/Program.cs#snippet0)] + +### [Visual Basic](#tab/vb) +[!code-vb[](../../samples/word/replace_the_theme_part/vb/Program.vb#snippet0)] +*** + +## See also + + + +- [Open XML SDK class library reference](/office/open-xml/open-xml-sdk) diff --git a/docs/general/how-to-search-and-replace-text-in-a-document-part.md b/docs/general/how-to-search-and-replace-text-in-a-document-part.md new file mode 100644 index 00000000..4c72808a --- /dev/null +++ b/docs/general/how-to-search-and-replace-text-in-a-document-part.md @@ -0,0 +1,92 @@ +--- + +api_name: +- Microsoft.Office.DocumentFormat.OpenXML.Packaging +api_type: +- schema +ms.assetid: cbb4547e-45fa-48ee-872e-8727beec6dfa +title: 'How to: Search and replace text in a document part' +ms.suite: office + +ms.author: o365devx +author: o365devx +ms.topic: conceptual +ms.date: 11/01/2017 +ms.localizationpriority: high +--- +# Search and replace text in a document part + +This topic shows how to use the classes in the Open XML SDK for +Office to programmatically search and replace a text value in a word +processing document. + + + +-------------------------------------------------------------------------------- +[!include[Structure](../includes/word/packages-and-document-parts.md)] + + +--------------------------------------------------------------------------------- +## Getting a WordprocessingDocument Object + +In the sample code, you start by opening the word processing file by +instantiating the class as shown in +the following `using` statement. In the same +statement, you open the word processing file `document` by using the + method, with the Boolean parameter set +to `true` to enable editing the document. + +### [C#](#tab/cs-1) +[!code-csharp[](../../samples/word/search_and_replace_text_a_part/cs/Program.cs#snippet1)] + +### [Visual Basic](#tab/vb-1) +[!code-vb[](../../samples/word/search_and_replace_text_a_part/vb/Program.vb#snippet1)] +*** + + +[!include[Using Statement](../includes/word/using-statement.md)] + + +-------------------------------------------------------------------------------- +## Sample Code + +The following example demonstrates a quick and easy way to search and +replace. It may not be reliable because it retrieves the XML document in +string format. Depending on the regular expression you might +unintentionally replace XML tags and corrupt the document. If you simply +want to search a document, but not replace the contents you can use +`MainDocumentPart.Document.InnerText`. + +This example also shows how to use a regular expression to search and +replace the text value, "Hello World!" stored in a word processing file +with the value "Hi Everyone!". To call the method +`SearchAndReplace`, you can use the following +example. + +### [C#](#tab/cs-2) +[!code-csharp[](../../samples/word/search_and_replace_text_a_part/cs/Program.cs#snippet2)] + +### [Visual Basic](#tab/vb-2) +[!code-vb[](../../samples/word/search_and_replace_text_a_part/vb/Program.vb#snippet2)] +*** + + +After running the program, you can inspect the file to see the change in +the text, "Hello world!" + +The following is the complete sample code in both C\# and Visual Basic. + +### [C#](#tab/cs) +[!code-csharp[](../../samples/word/search_and_replace_text_a_part/cs/Program.cs#snippet0)] + +### [Visual Basic](#tab/vb) +[!code-vb[](../../samples/word/search_and_replace_text_a_part/vb/Program.vb#snippet0)] +*** + +-------------------------------------------------------------------------------- +## See also + + +- [Open XML SDK class library reference](/office/open-xml/open-xml-sdk) + +- [Regular Expressions](/dotnet/standard/base-types/regular-expressions) diff --git a/docs/general/introduction-to-markup-compatibility.md b/docs/general/introduction-to-markup-compatibility.md new file mode 100644 index 00000000..fbbc0d69 --- /dev/null +++ b/docs/general/introduction-to-markup-compatibility.md @@ -0,0 +1,104 @@ +--- + +api_name: +- Microsoft.Office.DocumentFormat.OpenXML.Packaging +api_type: +- schema +ms.assetid: dd42a9a3-5c16-4cab-ad6d-506cf822ec7a +title: Introduction to markup compatibility +ms.suite: office + +ms.author: o365devx +author: o365devx +ms.topic: conceptual +ms.date: 01/08/2025 +ms.localizationpriority: high +--- + +# Introduction to markup compatibility + +This topic introduces the markup compatibility features included in the Open XML SDK for Office. + +## Introduction + +Suppose you have a Microsoft Word 365 document that employs a feature introduced in Microsoft Office 365. When you open that document in Microsoft Word 2016, an earlier version, what should happen? Ideally, you want the document to remain interoperable with Word 2016, even though Word 2016 will not understand the new feature. + +Consider also what should happen if you open that document in a hypothetical later version of Office. Here too, you want the document to work as expected. That is, you want the later version of Office to understand and support a feature employed in a document produced by Word 365. + +Open XML anticipates these scenarios. The Office Open XML File Formats specification describes facilities for achieving the above desired outcomes in [ECMA-376, Second Edition, Part 3 - Markup Compatibility and Extensibility](https://www.ecma-international.org/publications-and-standards/standards/ecma-376/). + +The Open XML SDK supports markup compatibility in a way that makes it easy for you to achieve the above desired outcomes for and Office 365 without having to necessarily become an expert in the specification details. + +## What is markup compatibility? + +Open XML defines formats for word-processing, spreadsheet and presentation documents in the form of specific markup languages, namely WordprocessingML, SpreadsheetML, and PresentationML. With respect to the Open XML file formats, markup compatibility is the ability for a document expressed in one of the above markup languages to facilitate interoperability between applications, or versions of an application, with different feature sets. This is supported through the use of a defined set of XML elements and attributes in the Markup Compatibility namespace of the Open XML specification. Notice that while the markup is supported in the document format, markup producers and consumers, such as Microsoft Word, must support it as well. In other words, interoperability is a function of support both in the file format and by applications. + +## Markup compatibility in the Open XML file formats specification + +Markup compatibility is discussed in [ECMA-376, Second Edition, Part 3 - Markup Compatibility and Extensibility](https://www.ecma-international.org/wp-content/uploads/ECMA-376-3_5th_edition_december_2015.zip), which is recommended reading to understand markup compatibility. The specification defines XML attributes to express compatibility rules, and XML elements to specify alternate content. For example, the `Ignorable` attribute specifies namespaces that can be ignored when they are not understood by the consuming application. Alternate-Content elements specify markup alternatives that can be chosen by an application at run time. For example, Word 2013 can choose only the markup alternative that it recognizes. The complete list of compatibility-rule attributes and alternate-content elements and their details can be found in the specification. + +## Open XML SDK support for markup compatibility + +The work that the Open XML SDK does for markup compatibility is detailed and subtle. However, the goal can be summarized as: using settings that you assign when you open a document, preprocess the document to: + +1. Filter or remove any elements from namespaces that will not be understood (for example, Office 365 document opened in Office 2016 context) +2. Process any markup compatibility elements and attributes as specified in the Open XML specification. + +The preprocessing performed is in accordance with ECMA-376, Second Edition: Part 3.13. + +The Open XML SDK support for markup compatibility comes primarily in the form of two classes and in the manner in which content is preprocessed in accordance with ECMA-376, Second Edition. The two classes are `OpenSettings` and `MarkupCompatibilityProcessSettings`. Use the former to provide settings that apply to SDK behavior overall. Use the latter to supply one part of those settings, specifically those that apply to markup compatibility. + +## Set the stage when you open + +When you open a document using the Open XML SDK, you have the option of using an overload with a signature that accepts an instance of the class as a parameter. You use the open settings class to provide certain important settings that govern the behavior of the SDK. One set of settings in particular, stored in the property, determines how markup compatibility elements and attributes are processed. You set the property to an instance of the class prior to opening a document. + +The class has the following properties: + +- - Determines the parts that are preprocessed. + +- - Specifies the context that applies to preprocessing. + +By default, documents are not preprocessed. If however you do specify open settings and provide markup compatibility process settings, then the document is preprocessed in accordance with those settings. + +The following code example demonstrates how to call the Open method with an instance of the open settings class as a parameter. Notice that the `ProcessMode` and `TargetFileFormatVersions` properties are initialized as part of the `MarkupCompatiblityProcessSettings` constructor. + +```csharp + // Create instance of OpenSettings + OpenSettings openSettings = new OpenSettings(); + + // Add the MarkupCompatibilityProcessSettings + openSettings.MarkupCompatibilityProcessSettings = new MarkupCompatibilityProcessSettings( + MarkupCompatibilityProcessMode.ProcessAllParts, + FileFormatVersions.Office2007); + + // Open the document with OpenSettings + using (WordprocessingDocument wordDocument = WordprocessingDocument.Open(filename, true, openSettings)) + { + // ... more code here + } +``` + +## What happens during preprocessing + +During preprocessing, the Open XML SDK removes elements and attributes in the markup compatibility namespace, removing the contents of unselected alternate-content elements, and interpreting compatibility-rule attributes as appropriate. This work is guided by the process mode and target file format versions properties. + +The `ProcessMode` property determines the parts to be preprocessed. The content in *those* parts is filtered to contain only elements that are understood by the application version indicated in the `TargetFileFormatVersions` property. + +> [!WARNING] +> Preprocessing affects what gets saved. When you save a file, the only markup that is saved is that which remains after preprocessing. + +## Understand process mode + +The process mode specifies which document parts should be preprocessed. You set this property to a member of the enumeration. The default value, `NoProcess`, indicates that no preprocessing is performed. Your application must be able to understand and handle any elements and attributes present in the document markup, including any of the elements and attributes in the Markup Compatibility namespace. + +You might want to work on specific document parts while leaving the rest untouched. For example, you might want to ensure minimal modification to the file. In that case, specify `ProcessLoadedPartsOnly` for the process mode. With this setting, preprocessing and the associated filtering is only applied to the loaded document parts, not the entire document. + +Finally, there is `ProcessAllParts`, which specifies what the name implies. When you choose this value, the entire document is preprocessed. + +## Set the target file format version + +The target file format versions property lets you choose to process markup compatibility content in the context of a specific Office version, e.g. Office 365. Set the `TargetFileFormatVersions` property to a member of the enumeration. + +The default value, `Office2007`, means the SDK will assume that namespaces defined in Office 2007 are understood, but not namespaces defined in Office 2010 or later. Thus, during preprocessing, the SDK will ignore the namespaces defined in newer Office versions and choose the Office 2007 compatible alternate-content. + +When you set the target file format versions property to `Office2013`, the Open XML SDK assumes that all of the namespaces defined in Office 2010 and Office 2013 are understood, does not ignore any content defined under Office 2013, and will choose the Office 2013 compatible alternate-content. diff --git a/docs/packages-and-general.md b/docs/general/overview.md similarity index 57% rename from docs/packages-and-general.md rename to docs/general/overview.md index 33dc1085..32a0e485 100644 --- a/docs/packages-and-general.md +++ b/docs/general/overview.md @@ -5,40 +5,44 @@ api_name: api_type: - schema ms.assetid: edbe267a-ced9-43fd-a702-fd0165cb3438 -title: Packages and general (Open XML SDK) +title: Packages and general ms.suite: office ms.author: o365devx author: o365devx ms.topic: conceptual -ms.date: 11/01/2017 +ms.date: 01/03/2025 ms.localizationpriority: high --- -# Packages and general (Open XML SDK) -This section provides how-to topics for working with documents and packages using the Open XML SDK 2.5. +# Packages and general +This section provides how-to topics for working with documents and packages using the Open XML SDK. ## In this section -- [Add a new document part that receives a relationship ID to a package](how-to-add-a-new-document-part-that-receives-a-relationship-id-to-a-package.md) +- [Features in Open XML SDK](features.md) -- [Add a new document part to a package](how-to-add-a-new-document-part-to-a-package.md) +- [Introduction to markup compatibility](introduction-to-markup-compatibility.md) -- [Copy the contents of an Open XML package part to a document part in a different package](how-to-copy-the-contents-of-an-open-xml-package-part-to-a-document-part-in-a-dif.md) +- [Add a new document part that receives a relationship ID to a package](how-to-add-a-new-document-part-that-receives-a-relationship-id-to-a-package.md) -- [Create a package](how-to-create-a-package.md) +- [Add a new document part to a package](how-to-add-a-new-document-part-to-a-package.md) -- [Get the contents of a document part from a package](how-to-get-the-contents-of-a-document-part-from-a-package.md) +- [Copy the contents of an Open XML package part to a document part in a different package](how-to-copy-the-contents-of-an-open-xml-package-part-to-a-document-part-in-a-dif.md) -- [Remove a document part from a package](how-to-remove-a-document-part-from-a-package.md) +- [Create a package](how-to-create-a-package.md) -- [Replace the theme part in a word processing document](how-to-replace-the-theme-part-in-a-word-processing-document.md) +- [Get the contents of a document part from a package](how-to-get-the-contents-of-a-document-part-from-a-package.md) -- [Search and replace text in a document part](how-to-search-and-replace-text-in-a-document-part.md) +- [Remove a document part from a package](how-to-remove-a-document-part-from-a-package.md) +- [Replace the theme part in a word processing document](how-to-replace-the-theme-part-in-a-word-processing-document.md) -## Related sections +- [Search and replace text in a document part](how-to-search-and-replace-text-in-a-document-part.md) -- [How do I...](how-do-i.md) -- [Getting started with the Open XML SDK 2.5 for Office](getting-started.md) +- [Diagnostic IDs](diagnosticids.md) + +## Related sections + +- [Getting started with the Open XML SDK for Office](../getting-started.md) diff --git a/docs/getting-started.md b/docs/getting-started.md index 9b79fb18..e052e431 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -5,7 +5,7 @@ api_name: api_type: - schema ms.assetid: 7b729dda-bbb6-437e-93d6-7bfe7b8183fa -title: Getting started with the Open XML SDK 2.5 for Office +title: Getting started with the Open XML SDK ms.suite: office ms.author: o365devx @@ -15,26 +15,15 @@ ms.date: 11/01/2017 ms.localizationpriority: high --- -# Getting started with the Open XML SDK 2.5 for Office +# Getting started with the Open XML SDK -The Open XML SDK 2.5 for Office simplifies the task of manipulating Open XML packages and the underlying Open XML schema elements within a package. The classes in the Open XML SDK 2.5 encapsulate many common tasks that developers perform on Open XML packages, so that you can perform complex operations with just a few lines of code. +The Open XML SDK simplifies the task of manipulating Open XML packages and the underlying Open XML schema elements within a package. The classes in the Open XML SDK encapsulate many common tasks that developers perform on Open XML packages, so that you can perform complex operations with just a few lines of code. -[!include[Add-ins note](./includes/addinsnote.md)] +## Available packages -## Using the Classes in the Open XML SDK +The SDK is available as a collection of NuGet packages that support .NET 3.5+, .NET Standard 2.0, .NET 6+, and [other supported platforms](/dotnet/standard/net-standard) for those targets. For information about installing packages, please see [the NuGet documentation](/nuget/quickstart/install-and-use-a-package-in-visual-studio). The following are the available packages: -Using the classes in the Open XML SDK 2.5 is simple. When you have installed the Open XML SDK 2.5, open your existing project or application in Visual Studio, or create a new project or application. Then, in your project or application, add references to the following components. - -- **DocumentFormat.OpenXml** -- **WindowsBase** - -### To add a reference in a Microsoft Visual Studio 2008 project - -1. In Solution Explorer, right-click **References** and then click **Add Reference**. If the **References** node is not visible, click **Project** and then click **Show All Files**. -2. In the **Add Reference** dialog box, click **.NET**. -3. In the Component Name column, select the components (scroll if you need to), and then click **OK**. - -> [!TIP] -> To select more than one component, hold down the **Ctrl** key and click each component. - -The added components are displayed in the References section in Solution Explorer. +- [`DocumentFormat.OpenXml.Framework`](https://www.nuget.org/packages/DocumentFormat.OpenXml.Framework): This package contains the foundational framework that enables the SDK. This is a new package starting with v3.0 and contains many types that previously were included in `DocumentFormat.OpenXml`. +- [`DocumentFormat.OpenXml`](https://www.nuget.org/packages/DocumentFormat.OpenXml): This package contains all of the strongly typed classes for parts and elements. +- [`DocumentFormat.OpenXml.Features`](https://www.nuget.org/packages/DocumentFormat.OpenXml.Features): This package contains additional functionality that enables some opt-in features. +- [`DocumentFormat.OpenXml.Linq`](https://www.nuget.org/packages/DocumentFormat.OpenXml.Linq): This package contains a collection of all the fully qualified names for parts and elements to enable more efficient `Linq` usage. diff --git a/docs/how-do-i.md b/docs/how-do-i.md deleted file mode 100644 index 381b16fc..00000000 --- a/docs/how-do-i.md +++ /dev/null @@ -1,32 +0,0 @@ ---- - -api_name: -- Microsoft.Office.DocumentFormat.OpenXML.Packaging -api_type: -- schema -ms.assetid: b5cc0e8d-da79-482a-81fa-f18c18d29f6c -title: How do I... (Open XML SDK) -ms.suite: office - -ms.author: o365devx -author: o365devx -ms.topic: conceptual -ms.date: 11/01/2017 -ms.localizationpriority: high ---- -# How do I... (Open XML SDK) - -This section provides how-to topics for working with the Open XML SDK -2.5 for Office. - -[!include[Add-ins note](./includes/addinsnote.md)] - -## In this section - -[Presentations (Open XML SDK)](presentations.md) - -[Packages and general (Open XML SDK)](packages-and-general.md) - -[Spreadsheets (Open XML SDK)](spreadsheets.md) - -[Word processing (Open XML SDK)](word-processing.md) diff --git a/docs/how-to-accept-all-revisions-in-a-word-processing-document.md b/docs/how-to-accept-all-revisions-in-a-word-processing-document.md deleted file mode 100644 index dce33047..00000000 --- a/docs/how-to-accept-all-revisions-in-a-word-processing-document.md +++ /dev/null @@ -1,510 +0,0 @@ ---- -api_name: -- Microsoft.Office.DocumentFormat.OpenXML.Packaging -api_type: -- schema -ms.assetid: b3406fcc-f10b-4075-a18f-116400f35faf -title: 'How to: Accept all revisions in a word processing document (Open XML SDK)' -description: 'Learn how to accept all revisions in a word processing document using the Open XML SDK.' -ms.suite: office -ms.author: o365devx -author: o365devx -ms.topic: conceptual -ms.date: 06/30/2021 -ms.localizationpriority: high ---- - -# Accept all revisions in a word processing document (Open XML SDK) - -This topic shows how to use the Open XML SDK 2.5 for Office to accept all revisions in a word processing document programmatically. - -The following assembly directives are required to compile the code in this topic. - -```csharp - using DocumentFormat.OpenXml; - using DocumentFormat.OpenXml.Packaging; - using DocumentFormat.OpenXml.Wordprocessing; - using System.Linq; - using System.Collections.Generic; -``` - -```vb - Imports DocumentFormat.OpenXml - Imports DocumentFormat.OpenXml.Packaging - Imports DocumentFormat.OpenXml.Wordprocessing - Imports System.Linq - Imports System.Collections.Generic -``` - -## Open the Existing Document for Editing - -To open an existing document, you can instantiate the [WordprocessingDocument](https://msdn.microsoft.com/library/office/documentformat.openxml.packaging.wordprocessingdocument.aspx) class as shown in the following **using** statement. To do so, you open the word processing file with the specified *fileName* by using the [Open(String, Boolean)](https://msdn.microsoft.com/library/office/cc562234.aspx) method, with the Boolean parameter set to **true** in order to enable editing the document. - -```csharp - using (WordprocessingDocument wdDoc = WordprocessingDocument.Open(fileName, true)) - { - // Insert other code here. - } -``` - -```vb - Using wdDoc As WordprocessingDocument = WordprocessingDocument.Open(fileName, True) - ' Insert other code here. - End Using -``` - -The **using** statement provides a recommended alternative to the typical .Open, .Save, .Close sequence. It ensures that the **Dispose** method (internal method used by the Open XML SDK to clean up resources) is automatically called when the closing brace is reached. The block that follows the **using** statement establishes a scope for the object that is created or named in the **using** statement, in this case *wdDoc*. Because the **WordprocessingDocument** class in the Open XML SDK automatically saves and closes the object as part of its **System.IDisposable** implementation, and because **Dispose** is automatically called when you exit the block, you do not have to explicitly call **Save** and **Close** as long as you use **using**. - -## Structure of a WordProcessingML Document - -The basic document structure of a **WordProcessingML** document consists of the **document** and **body** elements, followed by one or more block level elements such as **p**, which represents a paragraph. A paragraph contains one or more **r** elements. The **r** stands for run, which is a region of text with a common set of properties, such as formatting. A run contains one or more **t** elements. The **t** element contains a range of text. The following code example shows the **WordprocessingML** markup for a document that contains the text "Example text." - -```xml - - - - - Example text. - - - - -``` - -Using the Open XML SDK 2.5, you can create document structure and content using strongly-typed classes that correspond to **WordprocessingML** elements. You will find these classes in the [DocumentFormat.OpenXml.Wordprocessing](https://msdn.microsoft.com/library/office/documentformat.openxml.wordprocessing.aspx) namespace. The following table lists the class names of the classes that correspond to the **document**, **body**, **p**, **r**, and **t** elements. - -| WordprocessingML Element | Open XML SDK 2.5 Class | Description | -|---|---|---| -| document | [Document](https://msdn.microsoft.com/library/office/documentformat.openxml.wordprocessing.document.aspx) | The root element for the main document part. | -| body | [Body](https://msdn.microsoft.com/library/office/documentformat.openxml.wordprocessing.body.aspx) | The container for the block level structures such as paragraphs, tables, annotations and others specified in the [ISO/IEC 29500](https://www.iso.org/standard/71691.html) specification. | -| p | [Paragraph](https://msdn.microsoft.com/library/office/documentformat.openxml.wordprocessing.paragraph.aspx) | A paragraph. | -| r | [Run](https://msdn.microsoft.com/library/office/documentformat.openxml.wordprocessing.run.aspx) | A run. | -| t | [Text](https://msdn.microsoft.com/library/office/documentformat.openxml.wordprocessing.text.aspx) | A range of text. | - -## ParagraphPropertiesChange Element - -When you accept a revision mark, you change the properties of a paragraph either by deleting an existing text or inserting a new text. In the following sections, you read about three elements that are used in the code to change the paragraph contents, mainly, `` (Revision Information for Paragraph Properties), **``** (Deleted Paragraph), and **``** (Inserted Table Row) elements. - -The following information from the [ISO/IEC 29500](https://www.iso.org/standard/71691.html) specification introduces the **ParagraphPropertiesChange** element (**pPrChange**). - -### *pPrChange (Revision Information for Paragraph Properties) - -This element specifies the details about a single revision to a set of paragraph properties in a WordprocessingML document. - -This element stores this revision as follows: - -- The child element of this element contains the complete set of paragraph properties which were applied to this paragraph before this revision. - -- The attributes of this element contain information about when this revision took place (in other words, when these properties became a "former" set of paragraph properties). - -Consider a paragraph in a WordprocessingML document which is centered, and this change in the paragraph properties is tracked as a revision. This revision would be specified using the following WordprocessingML markup. - -```xml - - - - - - -``` - -The element specifies that there was a revision to the paragraph properties at 01-01-2006 by Samantha Smith, and the previous set of paragraph properties on the paragraph was the null set (in other words, no paragraph properties explicitly present under the element). **pPr** **pPrChange** - -© ISO/IEC29500: 2008. - -## Deleted Element - -The following information from the [ISO/IEC 29500](https://www.iso.org/standard/71691.html) specification -introduces the Deleted element (**del**). - -### del (Deleted Paragraph) - -This element specifies that the paragraph mark delimiting the end of a paragraph within a WordprocessingML document shall be treated as deleted (in other words, the contents of this paragraph are no longer delimited by this paragraph mark, and are combined with the following paragraph—but those contents shall not automatically be marked as deleted) as part of a tracked revision. - -Consider a document consisting of two paragraphs (with each paragraph delimited by a pilcrow ¶): - -![Two paragraphs each delimited by a pilcrow](media/w-delparagraphs01.gif) If the physical character delimiting the end of the first paragraph is deleted and this change is tracked as a revision, the following will result: - -![Two paragraphs delimited by a single pilcrow](media/w-delparagraphs02.gif) -This revision is represented using the following WordprocessingML: - -```xml - - - - - - - - This is paragraph one. - - - - - This is paragraph two. - - -``` - -The **del** element on the run properties for -the first paragraph mark specifies that this paragraph mark was deleted, -and this deletion was tracked as a revision. - -© ISO/IEC29500: 2008. - -## The Inserted Element - -The following information from the [ISO/IEC 29500](https://www.iso.org/standard/71691.html) specification -introduces the Inserted element (**ins**). - -### ins (Inserted Table Row) - -This element specifies that the parent table row shall be treated as an -inserted row whose insertion has been tracked as a revision. This -setting shall not imply any revision state about the table cells in this -row or their contents (which must be revision marked independently), and -shall only affect the table row itself. - -Consider a two row by two column table in which the second row has been -marked as inserted using a revision. This requirement would be specified -using the following WordprocessingML: - -```xml - - - - - - - - - - - - - - - - - - - - - -``` - -The **ins** element on the table row properties for the second table row -specifies that this row was inserted, and this insertion was tracked as -a revision. - -© ISO/IEC29500: 2008. - -## How the Sample Code Works - -After you have opened the document in the using statement, you -instantiate the **Body** class, and then handle -the formatting changes by creating the *changes* **List**, and removing each change (the **w:pPrChange** element) from the **List**, which is the same as accepting changes. - -```csharp - Body body = wdDoc.MainDocumentPart.Document.Body; - - // Handle the formatting changes. - List changes = - body.Descendants() - .Where(c => c.Author.Value == authorName).Cast().ToList(); - - foreach (OpenXmlElement change in changes) - { - change.Remove(); - } -``` - -```vb - Dim body As Body = wdDoc.MainDocumentPart.Document.Body - - ' Handle the formatting changes. - Dim changes As List(Of OpenXmlElement) = _ - body.Descendants(Of ParagraphPropertiesChange)() _ - .Where(Function(c) c.Author.Value = authorName).Cast _ - (Of OpenXmlElement)().ToList() - - For Each change In changes - change.Remove() - Next -``` - -You then handle the deletions by constructing the *deletions* **List**, and removing each deletion element (**w:del**) from the **List**, which is similar to the process of -accepting deletion changes. - -```csharp - // Handle the deletions. - List deletions = - body.Descendants() - .Where(c => c.Author.Value == authorName).Cast().ToList(); - - deletions.AddRange(body.Descendants() - .Where(c => c.Author.Value == authorName).Cast().ToList()); - - deletions.AddRange(body.Descendants() - .Where(c => c.Author.Value == authorName).Cast().ToList()); - - foreach (OpenXmlElement deletion in deletions) - { - deletion.Remove(); - } -``` - -```vb - ' Handle the deletions. - Dim deletions As List(Of OpenXmlElement) = _ - body.Descendants(Of Deleted)() _ - .Where(Function(c) c.Author.Value = authorName).Cast _ - (Of OpenXmlElement)().ToList() - - deletions.AddRange(body.Descendants(Of DeletedRun)() _ - .Where(Function(c) c.Author.Value = authorName).Cast _ - (Of OpenXmlElement)().ToList()) - - deletions.AddRange(body.Descendants(Of DeletedMathControl)() _ - .Where(Function(c) c.Author.Value = authorName).Cast _ - (Of OpenXmlElement)().ToList()) - - For Each deletion In deletions - deletion.Remove() - Next -``` - -Finally, you handle the insertions by constructing the *insertions* **List** and inserting the new text by removing the -insertion element (**w:ins**), which is the -same as accepting the inserted text. - -```csharp - // Handle the insertions. - List insertions = - body.Descendants() - .Where(c => c.Author.Value == authorName).Cast().ToList(); - - insertions.AddRange(body.Descendants() - .Where(c => c.Author.Value == authorName).Cast().ToList()); - - insertions.AddRange(body.Descendants() - .Where(c => c.Author.Value == authorName).Cast().ToList()); - - Run lastInsertedRun = null; - foreach (OpenXmlElement insertion in insertions) - { - // Found new content. - // Promote them to the same level as node, and then delete the node. - foreach (var run in insertion.Elements()) - { - if (run == insertion.FirstChild) - { - lastInsertedRun = insertion.InsertAfterSelf(new Run(run.OuterXml)); - } - else - { - lastInsertedRun = lastInsertedRun.Insertion.InsertAfterSelf(new Run(run.OuterXml)); - } - } - insertion.RemoveAttribute("rsidR", - "https://schemas.openxmlformats.org/wordprocessingml/2006/main"); - insertion.RemoveAttribute("rsidRPr", - "https://schemas.openxmlformats.org/wordprocessingml/2006/main"); - insertion.Remove(); - } -``` - -```vb - ' Handle the insertions. - Dim insertions As List(Of OpenXmlElement) = _ - body.Descendants(Of Inserted)() _ - .Where(Function(c) c.Author.Value = authorName).Cast _ - (Of OpenXmlElement)().ToList() - - insertions.AddRange(body.Descendants(Of InsertedRun)() _ - .Where(Function(c) c.Author.Value = authorName).Cast _ - (Of OpenXmlElement)().ToList()) - - insertions.AddRange(body.Descendants(Of InsertedMathControl)() _ - .Where(Function(c) c.Author.Value = authorName).Cast _ - (Of OpenXmlElement)().ToList()) - - Dim lastInsertedRun As Run = Nothing - For Each insertion In insertions - ' Found new content. Promote them to the same level as node, and then - ' delete the node. - For Each run In insertion.Elements(Of Run)() - If run Is insertion.FirstChild Then - lastInsertedRun = insertion.InsertAfterSelf(New Run(run.OuterXml)) - Else - lastInsertedRun = lastInsertedRun.Insertion.InsertAfterSelf(New Run(run.OuterXml)) - End If - Next - insertion.RemoveAttribute("rsidR", _ - "https://schemas.openxmlformats.org/wordprocessingml/2006/main") - insertion.RemoveAttribute("rsidRPr", _ - "https://schemas.openxmlformats.org/wordprocessingml/2006/main") - insertion.Remove() - Next -``` - -## Sample Code - -The following code example shows how to accept the entire revisions in a -word processing document. To run the program, you can call the method -**AcceptRevisions** to accept revisions in the -file "word1.docx" as in the following example. - -```csharp - string docName = @"C:\Users\Public\Documents\word1.docx"; - string authorName = "Katie Jordan"; - AcceptRevisions(docName, authorName); -``` - -```vb - Dim docName As String = "C:\Users\Public\Documents\word1.docx" - Dim authorName As String = "Katie Jordan" - AcceptRevisions(docName, authorName) -``` - -After you have run the program, open the word processing file to make -sure that all revision marks have been accepted. - -The following is the complete sample code in both C\# and Visual Basic. - -```csharp - public static void AcceptRevisions(string fileName, string authorName) - { - // Given a document name and an author name, accept revisions. - using (WordprocessingDocument wdDoc = - WordprocessingDocument.Open(fileName, true)) - { - Body body = wdDoc.MainDocumentPart.Document.Body; - - // Handle the formatting changes. - List changes = - body.Descendants() - .Where(c => c.Author.Value == authorName).Cast().ToList(); - - foreach (OpenXmlElement change in changes) - { - change.Remove(); - } - - // Handle the deletions. - List deletions = - body.Descendants() - .Where(c => c.Author.Value == authorName).Cast().ToList(); - - deletions.AddRange(body.Descendants() - .Where(c => c.Author.Value == authorName).Cast().ToList()); - - deletions.AddRange(body.Descendants() - .Where(c => c.Author.Value == authorName).Cast().ToList()); - - foreach (OpenXmlElement deletion in deletions) - { - deletion.Remove(); - } - - // Handle the insertions. - List insertions = - body.Descendants() - .Where(c => c.Author.Value == authorName).Cast().ToList(); - - insertions.AddRange(body.Descendants() - .Where(c => c.Author.Value == authorName).Cast().ToList()); - - insertions.AddRange(body.Descendants() - .Where(c => c.Author.Value == authorName).Cast().ToList()); - - foreach (OpenXmlElement insertion in insertions) - { - // Found new content. - // Promote them to the same level as node, and then delete the node. - foreach (var run in insertion.Elements()) - { - if (run == insertion.FirstChild) - { - insertion.InsertAfterSelf(new Run(run.OuterXml)); - } - else - { - insertion.NextSibling().InsertAfterSelf(new Run(run.OuterXml)); - } - } - insertion.RemoveAttribute("rsidR", - "https://schemas.openxmlformats.org/wordprocessingml/2006/main"); - insertion.RemoveAttribute("rsidRPr", - "https://schemas.openxmlformats.org/wordprocessingml/2006/main"); - insertion.Remove(); - } - } - } -``` - -```vb - Public Sub AcceptRevisions(ByVal fileName As String, ByVal authorName As String) - ' Given a document name and an author name, accept revisions. - Using wdDoc As WordprocessingDocument = WordprocessingDocument.Open(fileName, True) - Dim body As Body = wdDoc.MainDocumentPart.Document.Body - - ' Handle the formatting changes. - Dim changes As List(Of OpenXmlElement) = _ - body.Descendants(Of ParagraphPropertiesChange)() _ - .Where(Function(c) c.Author.Value = authorName).Cast(Of OpenXmlElement)().ToList() - - For Each change In changes - change.Remove() - Next - - ' Handle the deletions. - Dim deletions As List(Of OpenXmlElement) = _ - body.Descendants(Of Deleted)() _ - .Where(Function(c) c.Author.Value = authorName).Cast(Of OpenXmlElement)().ToList() - - deletions.AddRange(body.Descendants(Of DeletedRun)() _ - .Where(Function(c) c.Author.Value = authorName).Cast(Of OpenXmlElement)().ToList()) - - deletions.AddRange(body.Descendants(Of DeletedMathControl)() _ - .Where(Function(c) c.Author.Value = authorName).Cast(Of OpenXmlElement)().ToList()) - - For Each deletion In deletions - deletion.Remove() - Next - - ' Handle the insertions. - Dim insertions As List(Of OpenXmlElement) = _ - body.Descendants(Of Inserted)() _ - .Where(Function(c) c.Author.Value = authorName).Cast(Of OpenXmlElement)().ToList() - - insertions.AddRange(body.Descendants(Of InsertedRun)() _ - .Where(Function(c) c.Author.Value = authorName).Cast(Of OpenXmlElement)().ToList()) - - insertions.AddRange(body.Descendants(Of InsertedMathControl)() _ - .Where(Function(c) c.Author.Value = authorName).Cast(Of OpenXmlElement)().ToList()) - - For Each insertion In insertions - ' Found new content. Promote them to the same level as node, and then - ' delete the node. - For Each run In insertion.Elements(Of Run)() - If run Is insertion.FirstChild Then - insertion.InsertAfterSelf(New Run(run.OuterXml)) - Else - insertion.NextSibling().InsertAfterSelf(New Run(run.OuterXml)) - End If - Next - insertion.RemoveAttribute("rsidR", _ - "https://schemas.openxmlformats.org/wordprocessingml/2006/main") - insertion.RemoveAttribute("rsidRPr", _ - "https://schemas.openxmlformats.org/wordprocessingml/2006/main") - insertion.Remove() - Next - End Using - End Sub -``` - -## See also - -- [Open XML SDK 2.5 class library reference](/office/open-xml/open-xml-sdk.md) -- [Accepting Revisions in Open XML Word-Processing Documents](/previous-versions/office/developer/office-2007/ee836138) diff --git a/docs/how-to-add-a-comment-to-a-slide-in-a-presentation.md b/docs/how-to-add-a-comment-to-a-slide-in-a-presentation.md deleted file mode 100644 index 84889905..00000000 --- a/docs/how-to-add-a-comment-to-a-slide-in-a-presentation.md +++ /dev/null @@ -1,765 +0,0 @@ ---- - -api_name: -- Microsoft.Office.DocumentFormat.OpenXML.Packaging -api_type: -- schema -ms.assetid: 403abe97-7ab2-40ba-92c0-d6312a6d10c8 -title: 'How to: Add a comment to a slide in a presentation (Open XML SDK)' -ms.suite: office - -ms.author: o365devx -author: o365devx -ms.topic: conceptual -ms.date: 11/01/2017 -ms.localizationpriority: medium ---- - -# Add a comment to a slide in a presentation (Open XML SDK) - -This topic shows how to use the classes in the Open XML SDK 2.5 for -Office to add a comment to the first slide in a presentation -programmatically. - -The following assembly directives are required to compile the code in -this topic. - -```csharp - using System; - using System.Linq; - using DocumentFormat.OpenXml.Presentation; - using DocumentFormat.OpenXml.Packaging; -``` - -```vb - Imports System - Imports System.Linq - Imports DocumentFormat.OpenXml.Presentation - Imports DocumentFormat.OpenXml.Packaging -``` - -## Getting a PresentationDocument Object - -In the Open XML SDK, the [PresentationDocument](https://msdn.microsoft.com/library/office/documentformat.openxml.packaging.presentationdocument.aspx) class represents a -presentation document package. To work with a presentation document, -first create an instance of the **PresentationDocument** class, and then work with -that instance. To create the class instance from the document call the -[Open(String, Boolean)](https://msdn.microsoft.com/library/office/cc562287.aspx) method that uses a -file path, and a Boolean value as the second parameter to specify -whether a document is editable. To open a document for read/write, -specify the value **true** for this parameter -as shown in the following **using** statement. -In this code, the *file* parameter is a string that represents the path -for the file from which you want to open the document. - -```csharp - using (PresentationDocument doc = PresentationDocument.Open(file, true)) - { - // Insert other code here. - } -``` - -```vb - Using doc As PresentationDocument = PresentationDocument.Open(file, True) - ' Insert other code here. - End Using -``` - -The **using** statement provides a recommended -alternative to the typical .Open, .Save, .Close sequence. It ensures -that the **Dispose** method (internal method -used by the Open XML SDK to clean up resources) is automatically called -when the closing brace is reached. The block that follows the **using** statement establishes a scope for the -object that is created or named in the **using** statement, in this case *doc*. - - -## Basic Presentation Document Structure - -The basic document structure of a **PresentationML** document consists of a number of -parts, among which is the main part that contains the presentation -definition. The following text from the [ISO/IEC 29500](https://www.iso.org/standard/71691.html) specification -introduces the overall form of a **PresentationML** package. - -> The main part of a **PresentationML** package -> starts with a presentation root element. That element contains a -> presentation, which, in turn, refers to a **slide** list, a *slide master* list, a *notes -> master* list, and a *handout master* list. The slide list refers to -> all of the slides in the presentation; the slide master list refers to -> the entire slide masters used in the presentation; the notes master -> contains information about the formatting of notes pages; and the -> handout master describes how a handout looks. -> -> A *handout* is a printed set of slides that can be provided to an -> *audience*. -> -> As well as text and graphics, each slide can contain *comments* and -> *notes*, can have a *layout*, and can be part of one or more *custom -> presentations*. A comment is an annotation intended for the person -> maintaining the presentation slide deck. A note is a reminder or piece -> of text intended for the presenter or the audience. -> -> Other features that a **PresentationML** -> document can include the following: *animation*, *audio*, *video*, and -> *transitions* between slides. -> -> A **PresentationML** document is not stored -> as one large body in a single part. Instead, the elements that -> implement certain groupings of functionality are stored in separate -> parts. For example, all comments in a document are stored in one -> comment part while each slide has its own part. -> -> © ISO/IEC29500: 2008. - -The following XML code example represents a presentation that contains -two slides denoted by the IDs 267 and 256. - -```xml - - - - - - - - - - - - - - - - - -``` - -Using the Open XML SDK 2.5, you can create document structure and -content using strongly-typed classes that correspond to PresentationML -elements. You can find these classes in the [DocumentFormat.OpenXml.Presentation](https://msdn.microsoft.com/library/office/documentformat.openxml.presentation.aspx) -namespace. The following table lists the class names of the classes that -correspond to the **sld**, **sldLayout**, **sldMaster**, and **notesMaster** elements. - -| PresentationML Element | Open XML SDK 2.5 Class | Description | -|---|---|---| -| sld | [Slide](https://msdn.microsoft.com/library/office/documentformat.openxml.presentation.slide.aspx) | Presentation Slide. It is the root element of SlidePart. | -| sldLayout | [SlideLayout](https://msdn.microsoft.com/library/office/documentformat.openxml.presentation.slidelayout.aspx) | Slide Layout. It is the root element of SlideLayoutPart. | -| sldMaster | [SlideMaster](https://msdn.microsoft.com/library/office/documentformat.openxml.presentation.slidemaster.aspx) | Slide Master. It is the root element of SlideMasterPart. | -| notesMaster | [NotesMaster](https://msdn.microsoft.com/library/office/documentformat.openxml.presentation.notesmaster.aspx) | Notes Master (or handoutMaster). It is the root element of NotesMasterPart. | - - -## The Structure of the Comment Element - -A comment is a text note attached to a slide, with the primary purpose -of enabling readers of a presentation to provide feedback to the -presentation author. Each comment contains an unformatted text string -and information about its author, and is attached to a particular -location on a slide. Comments can be visible while editing the -presentation, but do not appear when a slide show is given. The -displaying application decides when to display comments and determines -their visual appearance. - -The following XML element specifies a single comment attached to a -slide. It contains the text of the comment (**text**), its position on the slide (**pos**), and attributes referring to its author -(**authorId**), date and time (**dt**), and comment index (**idx**). - -```xml - - - Add diagram to clarify. - -``` - -The following table contains the definitions of the members and -attributes of the **cm** (comment) element. - -| Member/Attribute | Definition | -|---|---| -| authorId | Refers to the ID of an author in the comment author list for the document. | -| dt | The date and time this comment was last modified. | -| idx | An identifier for this comment that is unique within a list of all comments by this author in this document. An author's first comment in a document has index 1. | -| pos | The positioning information for the placement of a comment on a slide surface. | -| text | Comment text. | -| extLst | Specifies the extension list with modification ability within which all future extensions of element type ext are defined. The extension list along with corresponding future extensions is used to extend the storage capabilities of the PresentationML framework. This allows for various new kinds of data to be stored natively within the framework. | - - -The following XML schema code example defines the members of the **cm** element in addition to the required and -optional attributes. - -```xml - - - - - - - - - - -``` - -## How the Sample Code Works - -The sample code opens the presentation document in the **using** statement. Then it instantiates the **CommentAuthorsPart**, and verifies that there is an -existing comment authors part. If there is not, it adds one. - -```csharp - // Declare a CommentAuthorsPart object. - CommentAuthorsPart authorsPart; - - // Verify that there is an existing comment authors part. - if (doc.PresentationPart.CommentAuthorsPart == null) - { - // If not, add a new one. - authorsPart = doc.PresentationPart.AddNewPart(); - } - else - { - authorsPart = doc.PresentationPart.CommentAuthorsPart; - } -``` - -```vb - ' Declare a CommentAuthorsPart object. - Dim authorsPart As CommentAuthorsPart - - ' Verify that there is an existing comment authors part. - If doc.PresentationPart.CommentAuthorsPart Is Nothing Then - ' If not, add a new one. - authorsPart = doc.PresentationPart.AddNewPart(Of CommentAuthorsPart)() - Else - authorsPart = doc.PresentationPart.CommentAuthorsPart - End If -``` - -The code determines whether there is an existing comment author list in -the comment-authors part; if not, it adds one. It also verifies that the -author that is passed in is on the list of existing comment authors; if -so, it assigns the existing author ID. If not, it adds a new author to -the list of comment authors and assigns an author ID and the parameter -values. - -```csharp - // Verify that there is a comment author list in the comment authors part. - if (authorsPart.CommentAuthorList == null) - { - // If not, add a new one. - authorsPart.CommentAuthorList = new CommentAuthorList(); - } - - // Declare a new author ID. - uint authorId = 0; - CommentAuthor author = null; - - // If there are existing child elements in the comment authors list... - if (authorsPart.CommentAuthorList.HasChildren) - { - // Verify that the author passed in is on the list. - var authors = authorsPart.CommentAuthorList.Elements().Where(a => a.Name == name && a.Initials == initials); - - // If so... - if (authors.Any()) - { - // Assign the new comment author the existing author ID. - author = authors.First(); - authorId = author.Id; - } - - // If not... - if (author == null) - { - // Assign the author passed in a new ID - authorId = authorsPart.CommentAuthorList.Elements().Select(a => a.Id.Value).Max(); - } - } - - // If there are no existing child elements in the comment authors list. - if (author == null) - { - authorId++; - - // Add a new child element(comment author) to the comment author list. - author = authorsPart.CommentAuthorList.AppendChild - (new CommentAuthor() - { - Id = authorId, - Name = name, - Initials = initials, - ColorIndex = 0 - }); - } -``` - -```vb - ' Verify that there is a comment author list in the comment authors part. - If authorsPart.CommentAuthorList Is Nothing Then - ' If not, add a new one. - authorsPart.CommentAuthorList = New CommentAuthorList() - End If - - ' Declare a new author ID. - Dim authorId As UInteger = 0 - Dim author As CommentAuthor = Nothing - - ' If there are existing child elements in the comment authors list... - If authorsPart.CommentAuthorList.HasChildren Then - ' Verify that the author passed in is on the list. - Dim authors = authorsPart.CommentAuthorList.Elements(Of CommentAuthor)().Where(Function(a) a.Name = name AndAlso a.Initials = initials) - - ' If so... - If authors.Any() Then - ' Assign the new comment author the existing author ID. - author = authors.First() - authorId = author.Id - End If - - ' If not... - If author Is Nothing Then - ' Assign the author passed in a new ID - authorId = authorsPart.CommentAuthorList.Elements(Of CommentAuthor)().Select(Function(a) a.Id.Value).Max() - End If - End If - - ' If there are no existing child elements in the comment authors list. - If author Is Nothing Then - authorId += 1 - - ' Add a new child element(comment author) to the comment author list. - author = authorsPart.CommentAuthorList.AppendChild(Of CommentAuthor) (New CommentAuthor() With {.Id = authorId, .Name = name, .Initials = initials, .ColorIndex = 0}) - End If -``` - -In the following code segment, the code gets the first slide in the -presentation by calling the *GetFirstSlide* method. Then it verifies -that there is a comments part in the slide; if not, it adds one. It also -verifies that a comments list exists in the comments part; if not, it -creates one. - -```csharp - // Get the first slide, using the GetFirstSlide method. - SlidePart slidePart1 = GetFirstSlide(doc); - - // Declare a comments part. - SlideCommentsPart commentsPart; - - // Verify that there is a comments part in the first slide part. - if (slidePart1.GetPartsOfType().Count() == 0) - { - // If not, add a new comments part. - commentsPart = slidePart1.AddNewPart(); - } - else - { - // Else, use the first comments part in the slide part. - commentsPart = slidePart1.SlideCommentsPart; - } - - // If the comment list does not exist. - if (commentsPart.CommentList == null) - { - // Add a new comments list. - commentsPart.CommentList = new CommentList(); - } -``` - -```vb - ' Get the first slide, using the GetFirstSlide method. - Dim slidePart1 As SlidePart = GetFirstSlide(doc) - - ' Declare a comments part. - Dim commentsPart As SlideCommentsPart - - ' Verify that there is a comments part in the first slide part. - If slidePart1.GetPartsOfType(Of SlideCommentsPart)().Count() = 0 Then - ' If not, add a new comments part. - commentsPart = slidePart1.AddNewPart(Of SlideCommentsPart)() - Else - ' Else, use the first comments part in the slide part. - commentsPart = slidePart1.SlideCommentsPart - End If - - ' If the comment list does not exist. - If commentsPart.CommentList Is Nothing Then - ' Add a new comments list. - commentsPart.CommentList = New CommentList() - End If -``` - -The code then gets the ID of the new comment, and adds the specified -comment, containing the specified text, at the specified position. Then -it saves the comment authors part and the comments part. - -```csharp - // Get the new comment ID. - uint commentIdx = author.LastIndex == null ? 1 : author.LastIndex + 1; - author.LastIndex = commentIdx; - - // Add a new comment. - Comment comment = commentsPart.CommentList.AppendChild( - new Comment() - { - AuthorId = authorId, - Index = commentIdx, - DateTime = DateTime.Now - }); - - // Add the position child node to the comment element. - comment.Append( - new Position() { X = 100, Y = 200 }, - new Text() { Text = text }); - - // Save the comment authors part. - authorsPart.CommentAuthorList.Save(); - - // Save the comments part. - commentsPart.CommentList.Save(); -``` - -```vb - ' Get the new comment ID. - Dim commentIdx As UInteger = If(author.LastIndex Is Nothing, 1, author.LastIndex + 1) - author.LastIndex = commentIdx - - ' Add a new comment. - Dim comment As Comment = commentsPart.CommentList.AppendChild(Of Comment)(New Comment() With {.AuthorId = authorId, .Index = commentIdx, .DateTime = Date.Now}) - - ' Add the position child node to the comment element. - comment.Append(New Position() With {.X = 100, .Y = 200}, New Text() With {.Text = text}) - - ' Save the comment authors part. - authorsPart.CommentAuthorList.Save() - - ' Save the comments part. - commentsPart.CommentList.Save() -``` - -## Sample Code - -The **AddCommentToPresentation** method can be -used to add a comment to a slide. The method takes as parameters the -source presentation file name and path, the initials and name of the -comment author, and the text of the comment to be added. It adds an -author to the list of comment authors and then adds the specified -comment text at the specified coordinates in the first slide in the -presentation. - -The second method, **GetFirstSlide**, is used -to get the first slide in the presentation. It takes the **PresentationDocument** object passed in, gets its -presentation part, and then gets the ID of the first slide in its slide -list. It then gets the relationship ID of the slide, gets the slide part -from the relationship ID, and returns the slide part to the calling -method. - -The following code example shows a call to the **AddCommentToPresentation** which adds the specified -comment string to the first slide in the presentation file Myppt1.pptx. - -```csharp - AddCommentToPresentation(@"C:\Users\Public\Documents\Myppt1.pptx", - "Katie Jordan", "KJ", - "This is my programmatically added comment."); -``` - -```vb - AddCommentToPresentation("C:\Users\Public\Documents\Myppt1.pptx", _ - "Katie Jordan", "KJ", _ - "This is my programmatically added comment.") -``` - -> [!NOTE] -> To get the exact author name and initials, open the presentation file and click the **File** menu item, and then click **Options**. The **PowerPointOptions** window opens and the content of the **General** tab is displayed. The author name and initials must match the **User name** and **Initials** in this tab. - - -```csharp - // Adds a comment to the first slide of the presentation document. - // The presentation document must contain at least one slide. - public static void AddCommentToPresentation(string file, string initials, string name, string text) - { - using (PresentationDocument doc = PresentationDocument.Open(file, true)) - { - - // Declare a CommentAuthorsPart object. - CommentAuthorsPart authorsPart; - - // Verify that there is an existing comment authors part. - if (doc.PresentationPart.CommentAuthorsPart == null) - { - // If not, add a new one. - authorsPart = doc.PresentationPart.AddNewPart(); - } - else - { - authorsPart = doc.PresentationPart.CommentAuthorsPart; - } - - // Verify that there is a comment author list in the comment authors part. - if (authorsPart.CommentAuthorList == null) - { - // If not, add a new one. - authorsPart.CommentAuthorList = new CommentAuthorList(); - } - - // Declare a new author ID. - uint authorId = 0; - CommentAuthor author = null; - - // If there are existing child elements in the comment authors list... - if (authorsPart.CommentAuthorList.HasChildren) - { - // Verify that the author passed in is on the list. - var authors = authorsPart.CommentAuthorList.Elements().Where(a => a.Name == name && a.Initials == initials); - - // If so... - if (authors.Any()) - { - // Assign the new comment author the existing author ID. - author = authors.First(); - authorId = author.Id; - } - - // If not... - if (author == null) - { - // Assign the author passed in a new ID - authorId = authorsPart.CommentAuthorList.Elements().Select(a => a.Id.Value).Max(); - } - } - - // If there are no existing child elements in the comment authors list. - if (author == null) - { - - authorId++; - - // Add a new child element(comment author) to the comment author list. - author = authorsPart.CommentAuthorList.AppendChild - (new CommentAuthor() - { - Id = authorId, - Name = name, - Initials = initials, - ColorIndex = 0 - }); - } - - // Get the first slide, using the GetFirstSlide method. - SlidePart slidePart1 = GetFirstSlide(doc); - - // Declare a comments part. - SlideCommentsPart commentsPart; - - // Verify that there is a comments part in the first slide part. - if (slidePart1.GetPartsOfType().Count() == 0) - { - // If not, add a new comments part. - commentsPart = slidePart1.AddNewPart(); - } - else - { - // Else, use the first comments part in the slide part. - commentsPart = slidePart1.GetPartsOfType().First(); - } - - // If the comment list does not exist. - if (commentsPart.CommentList == null) - { - // Add a new comments list. - commentsPart.CommentList = new CommentList(); - } - - // Get the new comment ID. - uint commentIdx = author.LastIndex == null ? 1 : author.LastIndex + 1; - author.LastIndex = commentIdx; - - // Add a new comment. - Comment comment = commentsPart.CommentList.AppendChild( - new Comment() - { - AuthorId = authorId, - Index = commentIdx, - DateTime = DateTime.Now - }); - - // Add the position child node to the comment element. - comment.Append( - new Position() { X = 100, Y = 200 }, - new Text() { Text = text }); - - // Save the comment authors part. - authorsPart.CommentAuthorList.Save(); - - // Save the comments part. - commentsPart.CommentList.Save(); - } - } - // Get the slide part of the first slide in the presentation document. - public static SlidePart GetFirstSlide(PresentationDocument presentationDocument) - { - // Get relationship ID of the first slide - PresentationPart part = presentationDocument.PresentationPart; - SlideId slideId = part.Presentation.SlideIdList.GetFirstChild(); - string relId = slideId.RelationshipId; - - // Get the slide part by the relationship ID. - SlidePart slidePart = (SlidePart)part.GetPartById(relId); - - return slidePart; - } -``` - -```vb - ' Adds a comment to the first slide of the presentation document. - ' The presentation document must contain at least one slide. - Public Sub AddCommentToPresentation(ByVal file As String, _ - ByVal initials As String, _ - ByVal name As String, _ - ByVal text As String) - - Dim doc As PresentationDocument = _ - PresentationDocument.Open(file, True) - - Using (doc) - - ' Declare a CommentAuthorsPart object. - Dim authorsPart As CommentAuthorsPart - - ' Verify that there is an existing comment authors part. - If (doc.PresentationPart.CommentAuthorsPart Is Nothing) Then - - ' If not, add a new one. - authorsPart = doc.PresentationPart.AddNewPart(Of CommentAuthorsPart)() - Else - authorsPart = doc.PresentationPart.CommentAuthorsPart - End If - - ' Verify that there is a comment author list in the comment authors part. - If (authorsPart.CommentAuthorList Is Nothing) Then - - ' If not, add a new one. - authorsPart.CommentAuthorList = New CommentAuthorList() - End If - - ' Declare a new author ID. - Dim authorId As UInteger = 0 - Dim author As CommentAuthor = Nothing - - ' If there are existing child elements in the comment authors list. - If authorsPart.CommentAuthorList.HasChildren = True Then - - ' Verify that the author passed in is on the list. - Dim authors = authorsPart.CommentAuthorList.Elements(Of CommentAuthor)().Where _ - (Function(a) a.Name = name AndAlso a.Initials = initials) - - ' If so... - If (authors.Any()) Then - - ' Assign the new comment author the existing ID. - author = authors.First() - authorId = author.Id - End If - - ' If not... - If (author Is Nothing) Then - - ' Assign the author passed in a new ID. - authorId = _ - authorsPart.CommentAuthorList.Elements(Of CommentAuthor)().Select(Function(a) a.Id.Value).Max() - End If - - End If - - ' If there are no existing child elements in the comment authors list. - If (author Is Nothing) Then - - authorId = authorId + 1 - - ' Add a new child element (comment author) to the comment author list. - author = (authorsPart.CommentAuthorList.AppendChild(Of CommentAuthor) _ - (New CommentAuthor() With {.Id = authorId, _ - .Name = name, _ - .Initials = initials, _ - .ColorIndex = 0})) - End If - - ' Get the first slide, using the GetFirstSlide() method. - Dim slidePart1 As SlidePart - slidePart1 = GetFirstSlide(doc) - - ' Declare a comments part. - Dim commentsPart As SlideCommentsPart - - ' Verify that there is a comments part in the first slide part. - If slidePart1.GetPartsOfType(Of SlideCommentsPart)().Count() = 0 Then - - ' If not, add a new comments part. - commentsPart = slidePart1.AddNewPart(Of SlideCommentsPart)() - Else - - ' Else, use the first comments part in the slide part. - commentsPart = _ - slidePart1.GetPartsOfType(Of SlideCommentsPart)().First() - End If - - ' If the comment list does not exist. - If (commentsPart.CommentList Is Nothing) Then - - ' Add a new comments list. - commentsPart.CommentList = New CommentList() - End If - - ' Get the new comment ID. - Dim commentIdx As UInteger - If author.LastIndex Is Nothing Then - commentIdx = 1 - Else - commentIdx = CType(author.LastIndex, UInteger) + 1 - End If - - author.LastIndex = commentIdx - - ' Add a new comment. - Dim comment As Comment = _ - (commentsPart.CommentList.AppendChild(Of Comment)(New Comment() _ - With {.AuthorId = authorId, .Index = commentIdx, .DateTime = DateTime.Now})) - - ' Add the position child node to the comment element. - comment.Append(New Position() With _ - {.X = 100, .Y = 200}, New Text() With {.Text = text}) - - - ' Save comment authors part. - authorsPart.CommentAuthorList.Save() - - ' Save comments part. - commentsPart.CommentList.Save() - - End Using - - End Sub - - ' Get the slide part of the first slide in the presentation document. - Public Function GetFirstSlide(ByVal presentationDocument As PresentationDocument) As SlidePart - ' Get relationship ID of the first slide - Dim part As PresentationPart = presentationDocument.PresentationPart - Dim slideId As SlideId = part.Presentation.SlideIdList.GetFirstChild(Of SlideId)() - Dim relId As String = slideId.RelationshipId - - ' Get the slide part by the relationship ID. - Dim slidePart As SlidePart = DirectCast(part.GetPartById(relId), SlidePart) - - Return slidePart - End Function - End Module -``` - -## See also - - - -- [Open XML SDK 2.5 class library reference](/office/open-xml/open-xml-sdk.md) - - diff --git a/docs/how-to-add-a-new-document-part-that-receives-a-relationship-id-to-a-package.md b/docs/how-to-add-a-new-document-part-that-receives-a-relationship-id-to-a-package.md deleted file mode 100644 index 82a366ea..00000000 --- a/docs/how-to-add-a-new-document-part-that-receives-a-relationship-id-to-a-package.md +++ /dev/null @@ -1,306 +0,0 @@ ---- - -api_name: -- Microsoft.Office.DocumentFormat.OpenXML.Packaging -api_type: -- schema -ms.assetid: c9b2ce55-548c-4443-8d2e-08fe1f06b7d7 -title: 'How to: Add a new document part that receives a relationship ID to a package' -ms.suite: office - -ms.author: o365devx -author: o365devx -ms.topic: conceptual -ms.date: 11/01/2017 -ms.localizationpriority: medium ---- - -# Add a new document part that receives a relationship ID to a package - -This topic shows how to use the classes in the Open XML SDK 2.5 for -Office to add a document part (file) that receives a relationship **Id** parameter for a word -processing document. - -The following assembly directives are required to compile the code in -this topic. - -```csharp - using System.IO; - using DocumentFormat.OpenXml; - using DocumentFormat.OpenXml.Packaging; - using DocumentFormat.OpenXml.Wordprocessing; - using System.Xml; -``` - -```vb - Imports System.IO - Imports DocumentFormat.OpenXml - Imports DocumentFormat.OpenXml.Packaging - Imports DocumentFormat.OpenXml.Wordprocessing - Imports System.Xml -``` - ------------------------------------------------------------------------------ -## Packages and Document Parts -An Open XML document is stored as a package, whose format is defined by -[ISO/IEC 29500-2](https://www.iso.org/standard/71691.html). The -package can have multiple parts with relationships between them. The -relationship between parts controls the category of the document. A -document can be defined as a word-processing document if its -package-relationship item contains a relationship to a main document -part. If its package-relationship item contains a relationship to a -presentation part it can be defined as a presentation document. If its -package-relationship item contains a relationship to a workbook part, it -is defined as a spreadsheet document. In this how-to topic, you will use -a word-processing document package. - - ------------------------------------------------------------------------------ -## The Structure of a WordProcessingML Document -The basic document structure of a **WordProcessingML** document consists of the **document** and **body** -elements, followed by one or more block level elements such as **p**, which represents a paragraph. A paragraph -contains one or more **r** elements. The **r** stands for run, which is a region of text with -a common set of properties, such as formatting. A run contains one or -more **t** elements. The **t** element contains a range of text. The following -code example shows the **WordprocessingML** -markup for a document that contains the text "Example text." - -```xml - - - - - Example text. - - - - -``` - -Using the Open XML SDK 2.5, you can create document structure and -content using strongly-typed classes that correspond to **WordprocessingML** elements. You will find these -classes in the [DocumentFormat.OpenXml.Wordprocessing](https://msdn.microsoft.com/library/office/documentformat.openxml.wordprocessing.aspx) -namespace. The following table lists the class names of the classes that -correspond to the **document**, **body**, **p**, **r**, and **t** elements. - -| WordprocessingML Element | Open XML SDK 2.5 Class | Description | -|---|---|---| -| document | [Document](https://msdn.microsoft.com/library/office/documentformat.openxml.wordprocessing.document.aspx) | The root element for the main document part. | -| body | [Body](https://msdn.microsoft.com/library/office/documentformat.openxml.wordprocessing.body.aspx) | The container for the block level structures such as paragraphs, tables, annotations and others specified in the ISO/IEC 29500 specification. | -| p | [Paragraph](https://msdn.microsoft.com/library/office/documentformat.openxml.wordprocessing.paragraph.aspx) | A paragraph. | -| r | [Run](https://msdn.microsoft.com/library/office/documentformat.openxml.wordprocessing.run.aspx) | A run. | -| t | [Text](https://msdn.microsoft.com/library/office/documentformat.openxml.wordprocessing.text.aspx) | A range of text. | - ------------------------------------------------------------------------------ -## How the Sample Code Works -The sample code, in this how-to, starts by passing in a parameter that -represents the path to the Word document. It then creates a document as -a **WordprocessingDocument** object. - -```csharp - public static void AddNewPart(string document) - { - // Create a new word processing document. - WordprocessingDocument wordDoc = - WordprocessingDocument.Create(document, - WordprocessingDocumentType.Document); -``` - -```vb - Public Shared Sub AddNewPart(ByVal document As String) - ' Create a new word processing document. - Dim wordDoc As WordprocessingDocument = _ - WordprocessingDocument.Create(document, WordprocessingDocumentType.Document) -``` - -It then adds the **MainDocumentPart** part in -the new word processing document, with the relationship ID, **rId1**. It also adds the **CustomFilePropertiesPart** part and a **CoreFilePropertiesPart** in the new word processing -document. - -```csharp - // Add the MainDocumentPart part in the new word processing document. - MainDocumentPart mainDocPart = wordDoc.AddNewPart - ("application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml", "rId1"); - mainDocPart.Document = new Document(); - - // Add the CustomFilePropertiesPart part in the new word processing document. - CustomFilePropertiesPart customFilePropPart = wordDoc.AddCustomFilePropertiesPart(); - customFilePropPart.Properties = new DocumentFormat.OpenXml.CustomProperties.Properties(); - - // Add the CoreFilePropertiesPart part in the new word processing document. - CoreFilePropertiesPart coreFilePropPart = wordDoc.AddCoreFilePropertiesPart(); - - using (XmlTextWriter writer = - new XmlTextWriter(coreFilePropPart.GetStream(FileMode.Create), System.Text.Encoding.UTF8)) - { - writer.WriteRaw("\r\n"); - writer.Flush(); - } -``` - -```vb - ' Add the MainDocumentPart part in the new word processing document. - Dim mainDocPart As MainDocumentPart = wordDoc.AddNewPart(Of MainDocumentPart) _ - ("application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml", "rId1") _ - mainDocPart.Document = New Document() - - ' Add the CustomFilePropertiesPart part in the new word processing document. - Dim customFilePropPart As CustomFilePropertiesPart = wordDoc.AddCustomFilePropertiesPart() - customFilePropPart.Properties = New DocumentFormat.OpenXml.CustomProperties.Properties() - - ' Add the CoreFilePropertiesPart part in the new word processing document. - Dim coreFilePropPart As CoreFilePropertiesPart = wordDoc.AddCoreFilePropertiesPart() - - Using writer As New XmlTextWriter(coreFilePropPart.GetStream(FileMode.Create), System.Text.Encoding.UTF8) - writer.WriteRaw("" _ - & vbCrLf & "") - writer.Flush() - End Using -``` - -The code then adds the **DigitalSignatureOriginPart** part, the **ExtendedFilePropertiesPart** part, and the **ThumbnailPart** part in the new word processing -document with realtionship IDs rId4, rId5, and rId6. And then it closes -the **wordDoc** object. - -```csharp - // Add the DigitalSignatureOriginPart part in the new word processing document. - wordDoc.AddNewPart("rId4"); - - // Add the ExtendedFilePropertiesPart part in the new word processing document.** - ExtendedFilePropertiesPart extendedFilePropPart = wordDoc.AddNewPart("rId5"); - extendedFilePropPart.Properties = new DocumentFormat.OpenXml.ExtendedProperties.Properties(); - - // Add the ThumbnailPart part in the new word processing document. - wordDoc.AddNewPart("image/jpeg", "rId6"); - - wordDoc.Close(); -``` - -```vb - ' Add the DigitalSignatureOriginPart part in the new word processing document. - wordDoc.AddNewPart(Of DigitalSignatureOriginPart)("rId4") - - ' Add the ExtendedFilePropertiesPart part in the new word processing document.** - Dim extendedFilePropPart As ExtendedFilePropertiesPart = wordDoc.AddNewPart(Of ExtendedFilePropertiesPart)("rId5") - extendedFilePropPart.Properties = New DocumentFormat.OpenXml.ExtendedProperties.Properties() - - ' Add the ThumbnailPart part in the new word processing document. - wordDoc.AddNewPart(Of ThumbnailPart)("image/jpeg", "rId6") - - wordDoc.Close() -``` - -> [!NOTE] -> The **AddNewPart<T>** method creates a relationship from the current document part to the new document part. This method returns the new document part. Also, you can use the **[DataPart.FeedData](https://msdn.microsoft.com/library/office/documentformat.openxml.packaging.datapart.feeddata.aspx)** method to fill the document part. - ------------------------------------------------------------------------------ -## Sample Code -The following code, adds a new document part that contains custom XML -from an external file and then populates the document part. You can call -the method **AddNewPart** by using a call like -the following code example. - -```csharp - string document = @"C:\Users\Public\Documents\MyPkg1.docx"; - AddNewPart(document); -``` - -```vb - Dim document As String = "C:\Users\Public\Documents\MyPkg1.docx" - AddNewPart(document) -``` - -The following is the complete code example in both C\# and Visual Basic. - -```csharp - public static void AddNewPart(string document) - { - // Create a new word processing document. - WordprocessingDocument wordDoc = - WordprocessingDocument.Create(document, - WordprocessingDocumentType.Document); - - // Add the MainDocumentPart part in the new word processing document. - var mainDocPart = wordDoc.AddNewPart - ("application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml", "rId1"); - mainDocPart.Document = new Document(); - - // Add the CustomFilePropertiesPart part in the new word processing document. - var customFilePropPart = wordDoc.AddCustomFilePropertiesPart(); - customFilePropPart.Properties = new DocumentFormat.OpenXml.CustomProperties.Properties(); - - // Add the CoreFilePropertiesPart part in the new word processing document. - var coreFilePropPart = wordDoc.AddCoreFilePropertiesPart(); - using (XmlTextWriter writer = new - XmlTextWriter(coreFilePropPart.GetStream(FileMode.Create), System.Text.Encoding.UTF8)) - { - writer.WriteRaw("\r\n"); - writer.Flush(); - } - - // Add the DigitalSignatureOriginPart part in the new word processing document. - wordDoc.AddNewPart("rId4"); - - // Add the ExtendedFilePropertiesPart part in the new word processing document. - var extendedFilePropPart = wordDoc.AddNewPart("rId5"); - extendedFilePropPart.Properties = - new DocumentFormat.OpenXml.ExtendedProperties.Properties(); - - // Add the ThumbnailPart part in the new word processing document. - wordDoc.AddNewPart("image/jpeg", "rId6"); - - wordDoc.Close(); - } -``` - -```vb - Public Sub AddNewPart(ByVal document As String) - ' Create a new word processing document. - Dim wordDoc As WordprocessingDocument = _ - WordprocessingDocument.Create(document, WordprocessingDocumentType.Document) - - ' Add the MainDocumentPart part in the new word processing document. - Dim mainDocPart = wordDoc.AddNewPart(Of MainDocumentPart) _ - ("application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml", "rId1") - mainDocPart.Document = New Document() - - ' Add the CustomFilePropertiesPart part in the new word processing document. - Dim customFilePropPart = wordDoc.AddCustomFilePropertiesPart() - customFilePropPart.Properties = New DocumentFormat.OpenXml.CustomProperties.Properties() - - ' Add the CoreFilePropertiesPart part in the new word processing document. - Dim coreFilePropPart = wordDoc.AddCoreFilePropertiesPart() - Using writer As New XmlTextWriter(coreFilePropPart.GetStream(FileMode.Create), _ - System.Text.Encoding.UTF8) - writer.WriteRaw( _ - "" & vbCr & vbLf & _ - "") - writer.Flush() - End Using - - ' Add the DigitalSignatureOriginPart part in the new word processing document. - wordDoc.AddNewPart(Of DigitalSignatureOriginPart)("rId4") - - ' Add the ExtendedFilePropertiesPart part in the new word processing document. - Dim extendedFilePropPart = wordDoc.AddNewPart(Of ExtendedFilePropertiesPart)("rId5") - extendedFilePropPart.Properties = _ - New DocumentFormat.OpenXml.ExtendedProperties.Properties() - - ' Add the ThumbnailPart part in the new word processing document. - wordDoc.AddNewPart(Of ThumbnailPart)("image/jpeg", "rId6") - - wordDoc.Close() - End Sub -``` - ------------------------------------------------------------------------------ -## See also - - -- [Open XML SDK 2.5 class library reference](/office/open-xml/open-xml-sdk.md) - - diff --git a/docs/how-to-add-a-new-document-part-to-a-package.md b/docs/how-to-add-a-new-document-part-to-a-package.md deleted file mode 100644 index 4e1f2ed6..00000000 --- a/docs/how-to-add-a-new-document-part-to-a-package.md +++ /dev/null @@ -1,166 +0,0 @@ ---- -api_name: -- Microsoft.Office.DocumentFormat.OpenXML.Packaging -api_type: -- schema -ms.assetid: ec83a076-9d71-49d1-915f-e7090f74c13a -title: 'How to: Add a new document part to a package (Open XML SDK)' -ms.suite: office -ms.author: o365devx -author: o365devx -ms.topic: conceptual -ms.date: 03/22/2022 -ms.localizationpriority: medium ---- - -# Add a new document part to a package (Open XML SDK) - -This topic shows how to use the classes in the Open XML SDK 2.5 for Office to add a document part (file) to a word processing document programmatically. - -The following assembly directives are required to compile the code in this topic. - -```csharp - using System.IO; - using DocumentFormat.OpenXml.Packaging; -``` - -```vb - Imports System.IO - Imports DocumentFormat.OpenXml.Packaging -``` - -## Packages and document parts - -An Open XML document is stored as a package, whose format is defined by [ISO/IEC 29500-2](https://www.iso.org/standard/71691.html). The package can have multiple parts with relationships between them. The relationship between parts controls the category of the document. A document can be defined as a word-processing document if its package-relationship item contains a relationship to a main document part. If its package-relationship item contains a relationship to a presentation part it can be defined as a presentation document. If its package-relationship item contains a relationship to a workbook part, it is defined as a spreadsheet document. In this how-to topic, you'll use a word-processing document package. - -## Get a WordprocessingDocument object - -The code starts with opening a package file by passing a file name to one of the overloaded **[Open()](https://msdn.microsoft.com/library/office/documentformat.openxml.packaging.wordprocessingdocument.open.aspx)** methods of the **[DocumentFormat.OpenXml.Packaging.WordprocessingDocument](https://msdn.microsoft.com/library/office/documentformat.openxml.packaging.wordprocessingdocument.aspx)** that takes a string and a Boolean value that specifies whether the file should be opened for editing or for read-only access. In this case, the Boolean value is **true** specifying that the file should be opened in read/write mode. - -```csharp - using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(document, true)) - { - // Insert other code here. - } -``` - -```vb - Using wordDoc As WordprocessingDocument = WordprocessingDocument.Open(document, True) - ' Insert other code here. - End Using -``` - -The **using** statement provides a recommended alternative to the typical .Create, .Save, .Close sequence. It ensures that the **Dispose** method (internal method used by the Open XML SDK to clean up resources) is automatically called when the closing brace is reached. The block that follows the **using** statement establishes a scope for the object that is created or named in the **using** statement, in this case **wordDoc**. Because the **WordprocessingDocument** class in the Open XML SDK -automatically saves and closes the object as part of its **System.IDisposable** implementation, and because the **Dispose** method is automatically called when you exit the block; you do not have to explicitly call **Save** and **Close**, as long as you use **using**. - -## Basic structure of a WordProcessingML document - -The basic document structure of a **WordProcessingML** document consists of the **document** and **body** elements, followed by one or more block level elements such as **p**, which represents a paragraph. A paragraph contains one or more **r** elements. The **r** stands for run, which is a region of text with a common set of properties, such as formatting. A run contains one or more **t** elements. The **t** element contains a range of text. The **WordprocessingML** markup for the document that the sample code creates is shown in the following code example. - -```xml - - - - - Create text in body - CreateWordprocessingDocument - - - - -``` - -Using the Open XML SDK 2.5, you can create document structure and content using strongly-typed classes that correspond to **WordprocessingML** elements. Find these classes in the **[DocumentFormat.OpenXml.Wordprocessing](https://msdn.microsoft.com/library/office/documentformat.openxml.wordprocessing.aspx)** namespace. The following table lists the class names of the classes that correspond to the **document**, **body**, **p**, **r**, and **t** elements, - -|**WordprocessingML Element** | **Open XML SDK 2.5 Class** | **Description** | -|:---|:---|:---| -| document | [Document](https://msdn.microsoft.com/library/office/documentformat.openxml.wordprocessing.document.aspx) | The root element for the main document part. | -| body | [Body](https://msdn.microsoft.com/library/office/documentformat.openxml.wordprocessing.body.aspx) | The container for the block level structures such as paragraphs, tables, annotations, and others specified in the ISO/IEC 29500 specification. | -| p | [Paragraph](https://msdn.microsoft.com/library/office/documentformat.openxml.wordprocessing.paragraph.aspx) | A paragraph. | -| r | [Run](https://msdn.microsoft.com/library/office/documentformat.openxml.wordprocessing.run.aspx) | A run. | -| t | [Text](https://msdn.microsoft.com/library/office/documentformat.openxml.wordprocessing.text.aspx) | A range of text. | - -## How the sample code works - -After opening the document for editing, in the **using** statement, as a **WordprocessingDocument** object, the code creates a reference to the **MainDocumentPart** part and adds a new custom XML part. It then reads the contents of the external -file that contains the custom XML and writes it to the **CustomXmlPart** part. - -> [!NOTE] -> To use the new document part in the document, add a link to the document part in the relationship part for the new part. - -```csharp - MainDocumentPart mainPart = wordDoc.MainDocumentPart; - CustomXmlPart myXmlPart = mainPart.AddCustomXmlPart(CustomXmlPartType.CustomXml); - - using (FileStream stream = new FileStream(fileName, FileMode.Open)) - { - myXmlPart.FeedData(stream); - } -``` - -```vb - Dim mainPart As MainDocumentPart = wordDoc.MainDocumentPart - - Dim myXmlPart As CustomXmlPart = mainPart.AddCustomXmlPart(CustomXmlPartType.CustomXml) - - Using stream As New FileStream(fileName, FileMode.Open) - myXmlPart.FeedData(stream) - End Using -``` - -## Sample code - -The following code adds a new document part that contains custom XML from an external file and then populates the part. To call the AddCustomXmlPart method in your program, use the following example that modifies the file "myPkg2.docx" by adding a new document part to it. - -```csharp - string document = @"C:\Users\Public\Documents\myPkg2.docx"; - string fileName = @"C:\Users\Public\Documents\myXML.xml"; - AddNewPart(document, fileName); -``` - -```vb - Dim document As String = "C:\Users\Public\Documents\myPkg2.docx" - Dim fileName As String = "C:\Users\Public\Documents\myXML.xml" - AddNewPart(document, fileName) -``` - -> [!NOTE] -> Before you run the program, change the Word file extension from .docx to .zip, and view the content of the zip file. Then change the extension back to .docx and run the program. After running the program, change the file extension again to .zip and view its content. You will see an extra folder named "customXML." This folder contains the XML file that represents the added part - -Following is the complete code example in both C\# and Visual Basic. - -```csharp - // To add a new document part to a package. - public static void AddNewPart(string document, string fileName) - { - using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(document, true)) - { - MainDocumentPart mainPart = wordDoc.MainDocumentPart; - - CustomXmlPart myXmlPart = mainPart.AddCustomXmlPart(CustomXmlPartType.CustomXml); - - using (FileStream stream = new FileStream(fileName, FileMode.Open)) - { - myXmlPart.FeedData(stream); - } - } - } -``` - -```vb - ' To add a new document part to a package. - Public Sub AddNewPart(ByVal document As String, ByVal fileName As String) - Using wordDoc As WordprocessingDocument = WordprocessingDocument.Open(document, True) - Dim mainPart As MainDocumentPart = wordDoc.MainDocumentPart - - Dim myXmlPart As CustomXmlPart = mainPart.AddCustomXmlPart(CustomXmlPartType.CustomXml) - - Using stream As New FileStream(fileName, FileMode.Open) - myXmlPart.FeedData(stream) - End Using - End Using - End Sub -``` - -## See also - -- [Open XML SDK 2.5 class library reference](/office/open-xml/open-xml-sdk) diff --git a/docs/how-to-add-custom-ui-to-a-spreadsheet-document.md b/docs/how-to-add-custom-ui-to-a-spreadsheet-document.md deleted file mode 100644 index 9dddafa1..00000000 --- a/docs/how-to-add-custom-ui-to-a-spreadsheet-document.md +++ /dev/null @@ -1,258 +0,0 @@ ---- - -api_name: -- Microsoft.Office.DocumentFormat.OpenXML.Packaging -api_type: -- schema -ms.assetid: fdb29547-c295-4e7d-9fc5-d86d8d8c2967 -title: 'How to: Add custom UI to a spreadsheet document (Open XML SDK)' -ms.suite: office - -ms.author: o365devx -author: o365devx -ms.topic: conceptual -ms.date: 11/01/2017 -ms.localizationpriority: high ---- - -# Add custom UI to a spreadsheet document (Open XML SDK) - -This topic shows how to use the classes in the Open XML SDK 2.5 for Office to programmatically add custom UI, modifying the ribbon, to an Microsoft Excel 2010 or Microsoft Excel 2013 worksheet. It contains an example **AddCustomUI** method to illustrate -this task. - -To use the sample code in this topic, you must install the [Open XML SDK 2.0](https://www.nuget.org/packages/DocumentFormat.OpenXml/2.5.0). Explicitly reference the following assemblies in your project: - -- WindowsBase -- DocumentFormat.OpenXml (installed by the Open XML SDK) - -You must also use the following **using** directives or **Imports** statements to compile the code in this topic. - -```csharp - using DocumentFormat.OpenXml.Office.CustomUI; - using DocumentFormat.OpenXml.Packaging; -``` - -```vb - Imports DocumentFormat.OpenXml.Office.CustomUI - Imports DocumentFormat.OpenXml.Packaging -``` - -## Creating Custom UI - -Before using the Open XML SDK 2.5 to create a ribbon customization in an Excel workbook, you must first create the customization content. Describing the XML required to create a ribbon customization is beyond the scope of this topic. In addition, you will find it far easier to use the Ribbon Designer in Visual Studio 2010 to create the customization for you. For more information about customizing the ribbon by using the Visual Studio Ribbon Designer, see [Ribbon Designer](https://msdn.microsoft.com/library/26617206-f4da-416f-a18a-d817b2d4872d(Office.15).aspx) and [Walkthrough: Creating a Custom Tab by Using the Ribbon Designer](https://msdn.microsoft.com/library/312865e6-950f-46ab-88de-fe7eb8036bfe(Office.15).aspx). -For the purposes of this demonstration, you will need an XML file that contains a customization, and the following code provides a simple customization (or you can create your own by using the Visual Studio Ribbon Designer, and then right-click to export the customization to an XML file). Copy the following content into a text file that is named AddCustomUI.xml for use as part of this example. This XML content describes a ribbon customization that includes a button labeled "Click Me!" in a group named Group1 on the **Add-Ins** tab in Excel. When you click the button, it attempts to run a macro named **SampleMacro** in the host workbook. - -```xml - - - - - -