[OpenXml] Pptxの境界線をWPFの境界線に変換

[OpenXml] Pptxの境界線をWPFの境界線に変換

テーマとしては

最后更新 2022/05/02 20:59
RyzenAdorer
预计阅读 3 分钟
分类
.NET
标签
.NET C# WPF OpenXML

1. Openxml SDKのインストール

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

  • nugetパッケージマネージャコンソール:
Install-Package dotnetCampus.DocumentFormat.OpenXml.Flatten -Version 2.0.0
  • CSPROJによると
<PackageReference Include="dotnetCampus.DocumentFormat.OpenXml.Flatten" Version="2.0.0" />

2. Pptxの解析

私はここでPPTXの7種類の線を使用して、それぞれ7種類の設定可能な破線タイプを設定して、PPTXの表示効果は次のようになります:

次のようにコードを解析します。主要論理部を解析します。

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

PPTXをWPF破線にマッピングする方法:

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

最終的に線を引く方法:

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

究極の効果:

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

3. 後の話。

実際、openxmlドキュメントはPresetDashの値を与えており、おおよそ次のようになります。

しかし、その値はWPFのDash DoubleCollection設定とは一致しないので、上記のマッピング値はすべて自分で微調整しました。

4. ソースコードソース

BlogCodeSample/PptDashConverToWpfSample at main · ZhengDaoWang/BlogCodeSample

Keep Exploring

延伸阅读

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

WPFは危険警告効果を達成する

私たちが書いたプログラムがリリースされると、ユーザーはいくつかの危険な操作を行っています。私たちのソフトウェアは、境界線のエッジが赤であるなど、いくつかのリマインダー効果を与える必要があります。

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

Code WF.EventBus:通信を円滑にする軽量イベントバス

Code WF.EventBusは、モジュール間のデカップリング通信を可能にする柔軟なイベントバスライブラリです。WPF、Win Forms、ASP.NET Coreなど、さまざまな. NETプロジェクトタイプをサポートしています。シンプルなデザインで、コマンドの発行とサブスクライブ、リクエストとレスポンスを簡単に実現できます。秩序あるインシデント処理により、インシデントが適切に処理されるようにする。コードを簡素化し、システムの保守性を向上させます。

继续阅读