[OpenXml] The dotted border of Pptx is changed to the dotted border of WPF

[OpenXml] The dotted border of Pptx is changed to the dotted border of WPF

if inscribe

最后更新 5/2/2022 8:59 PM
RyzenAdorer
预计阅读 3 分钟
分类
.NET
标签
.NET C# WPF OpenXML

1. Install Openxml sdk

首先,我们先安装 nuget 的需要的有关的 Openxml sdk,我们开源了解析 pptx 的Openxml 拍平层,下面两种方式都可以安装:

  • nuget Package Manager Console:
Install-Package dotnetCampus.DocumentFormat.OpenXml.Flatten -Version 2.0.0
  • Csproj quoted:
<PackageReference Include="dotnetCampus.DocumentFormat.OpenXml.Flatten" Version="2.0.0" />

2. Analyze Pptx

I use 7 types of straight lines of PPTX here to set 7 types of dotted lines that can be set. The display effect of PPTX is as follows:

Then parse the code as follows, parsing the main logical parts:

private void PptxToGeometry(string filePath)
{
    if (!File.Exists(filePath) || !filePath.EndsWith(".pptx", StringComparison.OrdinalIgnoreCase))
    {
        return;
    }

    var lines = new List<Line>();
    using var presentationDocument = PresentationDocument.Open(filePath, false);
    var presentationPart = presentationDocument.PresentationPart;
    var presentation = presentationPart?.Presentation;
    var slideIdList = presentation?.SlideIdList;
    if (slideIdList == null)
    {
        return;
    }
    foreach (var slideId in slideIdList.ChildElements.OfType<SlideId>())
    {
        var slidePart = (SlidePart)presentationPart.GetPartById(slideId.RelationshipId);
        var slide = slidePart.Slide;
        foreach (var shapeProperties in slide.Descendants<ShapeProperties>())
        {
            var presetGeometry = shapeProperties.GetFirstChild<PresetGeometry>();
            if (presetGeometry != null && presetGeometry.Preset.HasValue)
            {
                if (presetGeometry.Preset == ShapeTypeValues.StraightConnector1)
                {
                    var transform2D = shapeProperties.GetFirstChild<Transform2D>();
                    var extents = transform2D?.GetFirstChild<Extents>();
                    if (extents != null)
                    {
                        var width = new Emu(extents.Cx!.Value).ToPixel().Value;
                        var height = new Emu(extents.Cy!.Value).ToPixel().Value;


                        var presetDash = shapeProperties.GetFirstChild<Outline>()?.GetFirstChild<PresetDash>()?.Val;
                        var dashArray = GetDashArrayByPresetLineDashValues(presetDash);
                        var line = ConverterToGeometry( width, height, dashArray);
                        lines.Add(line);
                    }
                }
            }
        }
    }

    this.ListBox.ItemsSource = lines;
}

How to map PPTX to WPF dotted line:

private DoubleCollection GetDashArrayByPresetLineDashValues(PresetLineDashValues presetLineDashValues)
{
    DoubleCollection dashStyle = presetLineDashValues switch
    {
        PresetLineDashValues.Solid => new(),
        PresetLineDashValues.Dot => new() { 0, 2 },
        PresetLineDashValues.Dash => new() { 3, 3 },
        PresetLineDashValues.LargeDash => new() { 8, 3 },
        PresetLineDashValues.DashDot => new() { 3, 3, 1, 3 },
        PresetLineDashValues.LargeDashDot => new() { 7.5, 3.5, 1, 3.5 },
        PresetLineDashValues.LargeDashDotDot => new() { 8, 3, 1, 3, 1, 3 },
        PresetLineDashValues.SystemDash => new() { 3, 1 },
        PresetLineDashValues.SystemDot => new() { 1, 1 },
        PresetLineDashValues.SystemDashDot => new() { 2, 2, 0, 2 },
        PresetLineDashValues.SystemDashDotDot => new() { 2, 2, 0, 2 },
        _ => new DoubleCollection()
    };
    return dashStyle;
}

Final method of drawing lines:

private Line ConverterToGeometry(double width, double height, DoubleCollection dashDoubleCollection)
{
    var line = new Line
    {
        X1 = 0,
        Y1 = 0,
        X2 = width,
        Y2 = height,
        StrokeDashArray = dashDoubleCollection,
        Stroke = Stroke,
        StrokeThickness = StrokeThickness
    };
    return line;
}

Final effect:

我们可以看到几乎是接近的效果了,当然你也可以根据我的代码去微调更精确的值,只需要稍微改下GetDashArrayByPresetLineDashValues方法内相对应的值即可

3. a later story

In fact, the openxml document gives the value of PresetDash, which is roughly as follows:

However, its value does not correspond to the DoubleCollection setting of Dash in WPF, so the above mapping values are fine-tuned by me myself.

4. source code

BlogCodeSample/PptDashConverToWpfSample at main · ZhengDaoWang/BlogCodeSample

Keep Exploring

延伸阅读

更多文章
同分类 / 同标签 5/27/2025

WPF achieves a danger warning effect

When the program we write is released, the user is doing some dangerous operations. Our software should give some reminder effects, such as red on the edge of the border, similar to the alarm reminder effect like Gaode Map

继续阅读
同分类 / 同标签 6/20/2024

CodeWF.EventBus: Lightweight event bus for smoother communication

CodeWF.EventBus, a flexible event bus library that enables decoupling communication between modules. Supports multiple. NET project types, such as WPF, WinForms, ASP.NET Core, etc. Adopt concise design to easily implement command publishing and subscribing, request and response. Ensure that incidents are properly handled through orderly incident handling. Streamline your code and improve system maintainability.

继续阅读