diff --git a/docs/presentation/how-to-add-transitions-between-slides-in-a-presentation.md b/docs/presentation/how-to-add-transitions-between-slides-in-a-presentation.md new file mode 100644 index 0000000..2f230ba --- /dev/null +++ b/docs/presentation/how-to-add-transitions-between-slides-in-a-presentation.md @@ -0,0 +1,133 @@ +--- + +api_name: +- Microsoft.Office.DocumentFormat.OpenXML.Packaging +api_type: +- schema +ms.assetid: 5471f369-ad02-41c3-a5d3-ebaf618d185a +title: 'How to: Add transitions between slides in a presentation' +ms.suite: office + +ms.author: o365devx +author: o365devx +ms.topic: conceptual +ms.date: 04/03/2025 +ms.localizationpriority: medium +--- + +# Add Transitions between slides in a presentation + +This topic shows how to use the classes in the Open XML SDK to +add transition between all slides in a presentation programmatically. + +## Getting a Presentation Object + +In the Open XML SDK, the 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 + 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. + +### [C#](#tab/cs-1) +[!code-csharp[](../../samples/presentation/add_transition/cs/Program.cs#snippet1)] + +### [Visual Basic](#tab/vb-1) +[!code-vb[](../../samples/presentation/add_transition/vb/Program.vb#snippet1)] +*** + +[!include[Using Statement](../includes/presentation/using-statement.md)] `ppt`. + +## The Structure of the Transition + +Transition element `` specifies the kind of slide transition that should be used to transition to the current slide from the +previous slide. That is, the transition information is stored on the slide that appears after the transition is +complete. + +The following table lists the attributes of the Transition along +with the description of each. + +| Attribute | Description | +|---|---| +| advClick (Advance on Click) | Specifies whether a mouse click advances the slide or not. If this attribute is not specified then a value of true is assumed. | +| advTm (Advance after time) | Specifies the time, in milliseconds, after which the transition should start. This setting can be used in conjunction with the advClick attribute. If this attribute is not specified then it is assumed that no auto-advance occurs. | +| spd (Transition Speed) |Specifies the transition speed that is to be used when transitioning from the current slide to the next. | + +[*Example*: Consider the following example + +```xml + + + +``` +In the above example, the transition speed `` is set to slow (available options: slow, med, fast). Advance on Click `` is set to true, and Advance after time `` is set to 3000 milliseconds. The Random Bar child element `` describes the randomBar slide transition effect, which uses a set of randomly placed horizontal `` or vertical `` bars on the slide that continue to be added until the new slide is fully shown. *end example*] + +A full list of Transition's child elements can be viewed here: + +## The Structure of the Alternate Content + +Office Open XML defines a mechanism for the storage of content that is not defined by the ISO/IEC 29500 Office Open XML specification, such as extensions developed by future software applications that leverage the Office Open XML formats. This mechanism allows for the storage of a series of alternative representations of content, from which the consuming application can use the first alternative whose requirements are met. + +Consider an application that creates a new transition object intended to specify the duration of the transition. This functionality is not defined in the Office Open XML specification. Using an AlternateContent block as follows allows specifying the duration `` in milliseconds. + +[*Example*: +```xml + + + + + + + + + + + + +``` + +The Choice element in the above example requires the attribute to specify the duration of the transition, and the Fallback element allows clients that do not support this namespace to see an appropriate alternative representation. *end example*] + +More details on the P14 class can be found here: + +## How the Sample Code Works ## +After opening the presentation file for read/write access in the using statement, the code gets the presentation part from the presentation document. Then, it retrieves the relationship IDs of all slides in the presentation and gets the slides part from the relationship ID. The code then checks if there are no existing transitions set on the slides and replaces them with a new RandomBarTransition. + +### [C#](#tab/cs-2) +[!code-csharp[](../../samples/presentation/add_transition/cs/Program.cs#snippet2)] + +### [Visual Basic](#tab/vb-2) +[!code-vb[](../../samples/presentation/add_transition/vb/Program.vb#snippet2)] +*** + +If there are currently no transitions on the slide, code creates new transition. In both cases as a fallback transition, +RandomBarTransition is used but without `P14:dur`(duration) to allow grater support for clients that aren't supporting this namespace + +### [C#](#tab/cs-3) +[!code-csharp[](../../samples/presentation/add_transition/cs/Program.cs#snippet3)] + +### [Visual Basic](#tab/vb-3) +[!code-vb[](../../samples/presentation/add_transition/vb/Program.vb#snippet3)] +*** + +## Sample Code + +Following is the complete sample code that you can use to add RandomBarTransition to all slides. + +### [C#](#tab/cs) +[!code-csharp[](../../samples/presentation/add_transition/cs/Program.cs#snippet0)] + +### [Visual Basic](#tab/vb) +[!code-vb[](../../samples/presentation/add_transition/vb/Program.vb#snippet0)] +*** + +## See also + +- [Open XML SDK class library reference](/office/open-xml/open-xml-sdk) + + + + diff --git a/docs/presentation/overview.md b/docs/presentation/overview.md index ad9fb10..d223d2e 100644 --- a/docs/presentation/overview.md +++ b/docs/presentation/overview.md @@ -54,6 +54,8 @@ This section provides how-to topics for working with presentation documents usin - [Open a presentation document for read-only access](how-to-open-a-presentation-document-for-read-only-access.md) - [Retrieve the number of slides in a presentation document](how-to-retrieve-the-number-of-slides-in-a-presentation-document.md) + +- [Add a transition to a slides in a presentation](how-to-add-transitions-between-slides-in-a-presentation.md) - [Working with animation](working-with-animation.md) diff --git a/docs/toc.yml b/docs/toc.yml index 86bce97..e21f4f2 100644 --- a/docs/toc.yml +++ b/docs/toc.yml @@ -80,6 +80,8 @@ href: presentation/how-to-retrieve-the-number-of-slides-in-a-presentation-document.md - name: Structure of a PresentationML document href: presentation/structure-of-a-presentationml-document.md + - name: Add a transition to a slide in a presentation + href: presentation/how-to-add-transitions-between-slides-in-a-presentation.md - name: Working with animation href: presentation/working-with-animation.md - name: Working with comments diff --git a/samples/presentation/add_transition/cs/Program.cs b/samples/presentation/add_transition/cs/Program.cs new file mode 100644 index 0000000..497473e --- /dev/null +++ b/samples/presentation/add_transition/cs/Program.cs @@ -0,0 +1,119 @@ +using DocumentFormat.OpenXml; +using DocumentFormat.OpenXml.Presentation; +using DocumentFormat.OpenXml.Packaging; +using System.Collections.Generic; +using System.Linq; +using System; + +// +AddTransmitionToSlides(args[0]); +static void AddTransmitionToSlides(string filePath) +{ + // + using (PresentationDocument presentationDocument = PresentationDocument.Open(filePath, true)) + // + { + + // Check if the presentation part and slide list are available + if (presentationDocument.PresentationPart == null || presentationDocument.PresentationPart.Presentation.SlideIdList == null) + { + throw new NullReferenceException("Presentation part is empty or there are no slides"); + } + + // Get the presentation part + PresentationPart presentationPart = presentationDocument.PresentationPart; + + // Get the list of slide IDs + OpenXmlElementList slidesIds = presentationPart.Presentation.SlideIdList.ChildElements; + + // + // Define the transition start time and duration in milliseconds + string startTransitionAfterMs = "3000", durationMs = "2000"; + + // Set to true if you want to advance to the next slide on mouse click + bool advanceOnClick = true; + + // Iterate through each slide ID to get slides parts + foreach (SlideId slideId in slidesIds) + { + // Get the relationship ID of the slide + string? relId = slideId!.RelationshipId!.ToString(); + + if (relId == null) + { + throw new NullReferenceException("RelationshipId not found"); + } + + // Get the slide part using the relationship ID + SlidePart? slidePart = (SlidePart)presentationDocument.PresentationPart.GetPartById(relId); + + // Remove existing transitions if any + if (slidePart.Slide.Transition != null) + { + slidePart.Slide.Transition.Remove(); + } + + // Check if there are any AlternateContent elements + if (slidePart!.Slide.Descendants().ToList().Count > 0) + { + // Get all AlternateContent elements + List alternateContents = [.. slidePart.Slide.Descendants()]; + foreach (AlternateContent alternateContent in alternateContents) + { + // Remove transitions in AlternateContentChoice within AlternateContent + List childElements = alternateContent.ChildElements.ToList(); + + foreach (OpenXmlElement element in childElements) + { + List transitions = element.Descendants().ToList(); + foreach (Transition transition in transitions) + { + transition.Remove(); + } + } + // Add new transitions to AlternateContentChoice and AlternateContentFallback + alternateContent!.GetFirstChild(); + Transition choiceTransition = new Transition(new RandomBarTransition()) { Duration = durationMs, AdvanceAfterTime = startTransitionAfterMs, AdvanceOnClick = advanceOnClick, Speed = TransitionSpeedValues.Slow }; + Transition fallbackTransition = new Transition(new RandomBarTransition()) {AdvanceAfterTime = startTransitionAfterMs, AdvanceOnClick = advanceOnClick, Speed = TransitionSpeedValues.Slow }; + alternateContent!.GetFirstChild()!.Append(choiceTransition); + alternateContent!.GetFirstChild()!.Append(fallbackTransition); + } + } + // + + // + // Add transition if there is none + else + { + // Check if there is a transition appended to the slide and set it to null + if (slidePart.Slide.Transition != null) + { + slidePart.Slide.Transition = null; + } + // Create a new AlternateContent element + AlternateContent alternateContent = new AlternateContent(); + alternateContent.AddNamespaceDeclaration("mc", "http://schemas.openxmlformats.org/markup-compatibility/2006"); + + // Create a new AlternateContentChoice element and add the transition + AlternateContentChoice alternateContentChoice = new AlternateContentChoice() { Requires = "p14" }; + Transition choiceTransition = new Transition(new RandomBarTransition()) { Duration = durationMs, AdvanceAfterTime = startTransitionAfterMs, AdvanceOnClick = advanceOnClick, Speed = TransitionSpeedValues.Slow }; + Transition fallbackTransition = new Transition(new RandomBarTransition()) { AdvanceAfterTime = startTransitionAfterMs, AdvanceOnClick = advanceOnClick, Speed = TransitionSpeedValues.Slow }; + alternateContentChoice.Append(choiceTransition); + + // Create a new AlternateContentFallback element and add the transition + AlternateContentFallback alternateContentFallback = new AlternateContentFallback(fallbackTransition); + alternateContentFallback.AddNamespaceDeclaration("a14", "http://schemas.microsoft.com/office/drawing/2010/main"); + alternateContentFallback.AddNamespaceDeclaration("p16", "http://schemas.microsoft.com/office/powerpoint/2015/main"); + alternateContentFallback.AddNamespaceDeclaration("adec", "http://schemas.microsoft.com/office/drawing/2017/decorative"); + alternateContentFallback.AddNamespaceDeclaration("a16", "http://schemas.microsoft.com/office/drawing/2014/main"); + + // Append the AlternateContentChoice and AlternateContentFallback to the AlternateContent + alternateContent.Append(alternateContentChoice); + alternateContent.Append(alternateContentFallback); + slidePart.Slide.Append(alternateContent); + } + // + } + } +} +// diff --git a/samples/presentation/add_transition/cs/add_transition_cs.csproj b/samples/presentation/add_transition/cs/add_transition_cs.csproj new file mode 100644 index 0000000..1364b24 --- /dev/null +++ b/samples/presentation/add_transition/cs/add_transition_cs.csproj @@ -0,0 +1 @@ + diff --git a/samples/presentation/add_transition/vb/Program.vb b/samples/presentation/add_transition/vb/Program.vb new file mode 100644 index 0000000..30a1b8c --- /dev/null +++ b/samples/presentation/add_transition/vb/Program.vb @@ -0,0 +1,126 @@ +Imports DocumentFormat.OpenXml +Imports DocumentFormat.OpenXml.Packaging +Imports DocumentFormat.OpenXml.Presentation + +Module Program + Sub Main(args As String()) + AddTransmitionToSlides(args(0)) + End Sub + + ' + Sub AddTransmitionToSlides(filePath As String) + ' + Using presentationDocument As PresentationDocument = PresentationDocument.Open(filePath, True) + ' + ' Check if the presentation part and slide list are available + If presentationDocument.PresentationPart Is Nothing OrElse presentationDocument.PresentationPart.Presentation.SlideIdList Is Nothing Then + Throw New NullReferenceException("Presentation part is empty or there are no slides") + End If + + ' Get the presentation part + Dim presentationPart As PresentationPart = presentationDocument.PresentationPart + + ' Get the list of slide IDs + Dim slidesIds As OpenXmlElementList = presentationPart.Presentation.SlideIdList.ChildElements + + ' + ' Define the transition start time and duration in milliseconds + Dim startTransitionAfterMs As String = "3000" + Dim durationMs As String = "2000" + + ' Set to true if you want to advance to the next slide on mouse click + Dim advanceOnClick As Boolean = True + + ' Iterate through each slide ID to get slides parts + For Each slideId As SlideId In slidesIds + ' Get the relationship ID of the slide + Dim relId As String = slideId.RelationshipId.ToString() + + If relId Is Nothing Then + Throw New NullReferenceException("RelationshipId not found") + End If + + ' Get the slide part using the relationship ID + Dim slidePart As SlidePart = CType(presentationDocument.PresentationPart.GetPartById(relId), SlidePart) + + ' Remove existing transitions if any + If slidePart.Slide.Transition IsNot Nothing Then + slidePart.Slide.Transition.Remove() + End If + + ' Check if there are any AlternateContent elements + If slidePart.Slide.Descendants(Of AlternateContent)().ToList().Count > 0 Then + ' Get all AlternateContent elements + Dim alternateContents As List(Of AlternateContent) = slidePart.Slide.Descendants(Of AlternateContent)().ToList() + For Each alternateContent In alternateContents + ' Remove transitions in AlternateContentChoice within AlternateContent + Dim childElements As List(Of OpenXmlElement) = alternateContent.ChildElements.ToList() + + For Each element In childElements + Dim transitions As List(Of Transition) = element.Descendants(Of Transition)().ToList() + For Each transition In transitions + transition.Remove() + Next + Next + ' Add new transitions to AlternateContentChoice and AlternateContentFallback + alternateContent.GetFirstChild(Of AlternateContentChoice)() + Dim choiceTransition = New Transition(New RandomBarTransition()) With { + .Duration = durationMs, + .AdvanceAfterTime = startTransitionAfterMs, + .AdvanceOnClick = advanceOnClick, + .Speed = TransitionSpeedValues.Slow} + Dim fallbackTransition = New Transition(New RandomBarTransition()) With { + .AdvanceAfterTime = startTransitionAfterMs, + .AdvanceOnClick = advanceOnClick, + .Speed = TransitionSpeedValues.Slow} + alternateContent.GetFirstChild(Of AlternateContentChoice)().Append(choiceTransition) + alternateContent.GetFirstChild(Of AlternateContentFallback)().Append(fallbackTransition) + Next + ' + ' + ' Add transition if there is none + Else + ' Check if there is a transition appended to the slide and set it to null + If slidePart.Slide.Transition IsNot Nothing Then + slidePart.Slide.Transition = Nothing + End If + + ' Create a new AlternateContent element + Dim alternateContent As New AlternateContent() + alternateContent.AddNamespaceDeclaration("mc", "http://schemas.openxmlformats.org/markup-compatibility/2006") + + ' Create a new AlternateContentChoice element and add the transition + Dim alternateContentChoice As New AlternateContentChoice() With { + .Requires = "p14" + } + Dim choiceTransition = New Transition(New RandomBarTransition()) With { + .Duration = durationMs, + .AdvanceAfterTime = startTransitionAfterMs, + .AdvanceOnClick = advanceOnClick, + .Speed = TransitionSpeedValues.Slow} + alternateContentChoice.Append(choiceTransition) + + ' Create a new AlternateContentFallback element and add the transition + Dim fallbackTransition = New Transition(New RandomBarTransition()) With { + .AdvanceAfterTime = startTransitionAfterMs, + .AdvanceOnClick = advanceOnClick, + .Speed = TransitionSpeedValues.Slow} + Dim alternateContentFallback As New AlternateContentFallback(fallbackTransition) + + alternateContentFallback.AddNamespaceDeclaration("a14", "http://schemas.microsoft.com/office/drawing/2010/main") + alternateContentFallback.AddNamespaceDeclaration("p16", "http://schemas.microsoft.com/office/powerpoint/2015/main") + alternateContentFallback.AddNamespaceDeclaration("adec", "http://schemas.microsoft.com/office/drawing/2017/decorative") + alternateContentFallback.AddNamespaceDeclaration("a16", "http://schemas.microsoft.com/office/drawing/2014/main") + + ' Append the AlternateContentChoice and AlternateContentFallback to the AlternateContent + alternateContent.Append(alternateContentChoice) + alternateContent.Append(alternateContentFallback) + slidePart.Slide.Append(alternateContent) + End If + ' + Next + End Using + End Sub + +End Module +' diff --git a/samples/presentation/add_transition/vb/add_transition_vb.vbproj b/samples/presentation/add_transition/vb/add_transition_vb.vbproj new file mode 100644 index 0000000..1364b24 --- /dev/null +++ b/samples/presentation/add_transition/vb/add_transition_vb.vbproj @@ -0,0 +1 @@ + diff --git a/samples/samples.sln b/samples/samples.sln index 4b8cc8d..5aadc44 100644 --- a/samples/samples.sln +++ b/samples/samples.sln @@ -320,9 +320,9 @@ Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "working_with_tables_vb", "w EndProject Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "insert_a_picture_vb", "word\insert_a_picture\vb\insert_a_picture_vb.vbproj", "{6170C4E1-A109-435A-BF59-026C85B3BD9C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "add_video_cs", "presentation\add_video\cs\add_video_cs.csproj", "{9350E344-D11D-4496-9092-9BA18FC65175}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "add_transition_cs", "presentation\add_transition\cs\add_transition_cs.csproj", "{F61C7360-EB1B-4AF1-BD0D-257CAF122223}" EndProject -Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "add_video_vb", "presentation\add_video\vb\add_video_vb.vbproj", "{437E22AF-37F2-4D91-B508-2317AD5368BE}" +Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "add_transition_vb", "presentation\add_transition\vb\add_transition_vb.vbproj", "{58E15219-2772-42DC-8BB3-628811289B0F}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "add_audio_cs", "presentation\add_audio\cs\add_audio_cs.csproj", "{2BBA1942-8180-4435-A0A5-22811CC923FA}" EndProject Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "add_audio_vb", "presentation\add_audio\vb\add_audio_vb.vbproj", "{3327770E-D643-470A-88C7-9FE9483D2F43}" @@ -2187,6 +2187,30 @@ Global {6170C4E1-A109-435A-BF59-026C85B3BD9C}.Release|x64.Build.0 = Release|Any CPU {6170C4E1-A109-435A-BF59-026C85B3BD9C}.Release|x86.ActiveCfg = Release|Any CPU {6170C4E1-A109-435A-BF59-026C85B3BD9C}.Release|x86.Build.0 = Release|Any CPU + {F61C7360-EB1B-4AF1-BD0D-257CAF122223}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F61C7360-EB1B-4AF1-BD0D-257CAF122223}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F61C7360-EB1B-4AF1-BD0D-257CAF122223}.Debug|x64.ActiveCfg = Debug|Any CPU + {F61C7360-EB1B-4AF1-BD0D-257CAF122223}.Debug|x64.Build.0 = Debug|Any CPU + {F61C7360-EB1B-4AF1-BD0D-257CAF122223}.Debug|x86.ActiveCfg = Debug|Any CPU + {F61C7360-EB1B-4AF1-BD0D-257CAF122223}.Debug|x86.Build.0 = Debug|Any CPU + {F61C7360-EB1B-4AF1-BD0D-257CAF122223}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F61C7360-EB1B-4AF1-BD0D-257CAF122223}.Release|Any CPU.Build.0 = Release|Any CPU + {F61C7360-EB1B-4AF1-BD0D-257CAF122223}.Release|x64.ActiveCfg = Release|Any CPU + {F61C7360-EB1B-4AF1-BD0D-257CAF122223}.Release|x64.Build.0 = Release|Any CPU + {F61C7360-EB1B-4AF1-BD0D-257CAF122223}.Release|x86.ActiveCfg = Release|Any CPU + {F61C7360-EB1B-4AF1-BD0D-257CAF122223}.Release|x86.Build.0 = Release|Any CPU + {58E15219-2772-42DC-8BB3-628811289B0F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {58E15219-2772-42DC-8BB3-628811289B0F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {58E15219-2772-42DC-8BB3-628811289B0F}.Debug|x64.ActiveCfg = Debug|Any CPU + {58E15219-2772-42DC-8BB3-628811289B0F}.Debug|x64.Build.0 = Debug|Any CPU + {58E15219-2772-42DC-8BB3-628811289B0F}.Debug|x86.ActiveCfg = Debug|Any CPU + {58E15219-2772-42DC-8BB3-628811289B0F}.Debug|x86.Build.0 = Debug|Any CPU + {58E15219-2772-42DC-8BB3-628811289B0F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {58E15219-2772-42DC-8BB3-628811289B0F}.Release|Any CPU.Build.0 = Release|Any CPU + {58E15219-2772-42DC-8BB3-628811289B0F}.Release|x64.ActiveCfg = Release|Any CPU + {58E15219-2772-42DC-8BB3-628811289B0F}.Release|x64.Build.0 = Release|Any CPU + {58E15219-2772-42DC-8BB3-628811289B0F}.Release|x86.ActiveCfg = Release|Any CPU + {58E15219-2772-42DC-8BB3-628811289B0F}.Release|x86.Build.0 = Release|Any CPU {2BBA1942-8180-4435-A0A5-22811CC923FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2BBA1942-8180-4435-A0A5-22811CC923FA}.Debug|Any CPU.Build.0 = Debug|Any CPU {2BBA1942-8180-4435-A0A5-22811CC923FA}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -2385,8 +2409,8 @@ Global {A43A75AB-D6B6-4D31-99F7-6951AFEF502D} = {D207D3D7-FD4D-4FD4-A7D0-79A82086FB6F} {4EB1FCC9-E1E2-4D2A-ACF9-A3A31AA947A5} = {D207D3D7-FD4D-4FD4-A7D0-79A82086FB6F} {6170C4E1-A109-435A-BF59-026C85B3BD9C} = {D207D3D7-FD4D-4FD4-A7D0-79A82086FB6F} - {9350E344-D11D-4496-9092-9BA18FC65175} = {CDB9D4A6-7A7A-4CDF-A7A3-4F17F5F1602D} - {437E22AF-37F2-4D91-B508-2317AD5368BE} = {CDB9D4A6-7A7A-4CDF-A7A3-4F17F5F1602D} + {F61C7360-EB1B-4AF1-BD0D-257CAF122223} = {CDB9D4A6-7A7A-4CDF-A7A3-4F17F5F1602D} + {58E15219-2772-42DC-8BB3-628811289B0F} = {CDB9D4A6-7A7A-4CDF-A7A3-4F17F5F1602D} {2BBA1942-8180-4435-A0A5-22811CC923FA} = {CDB9D4A6-7A7A-4CDF-A7A3-4F17F5F1602D} {3327770E-D643-470A-88C7-9FE9483D2F43} = {CDB9D4A6-7A7A-4CDF-A7A3-4F17F5F1602D} {0AA6B9DD-2A2C-0E96-1052-6F4AC44B3F5D} = {7ACDC26B-C774-4004-8553-87E862D1E71F}