【OpenXml】Pptxの点線をWPFの点線に変換する

【OpenXml】Pptxの点線をWPFの点線に変換する

題の通り

最終更新 2022/05/02 20:59
RyzenAdorer
読了目安 3 分
カテゴリ
.NET
タグ
.NET C# WPF OpenXML

1. OpenXML SDK のインストール

まず、必要な OpenXML SDK の NuGet パッケージをインストールします。PPtx 解析用の Openxml フラット化 をオープンソースで公開しています。以下の 2 つの方法でインストールできます。

  • 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

さらに探索

関連読書

その他の記事
同じカテゴリ / 同じタグ 2025/05/27

WPFで危険警告効果を実現する

作成したプログラムをユーザーに配布した後、ユーザーが危険な操作を行っている場合、ソフトウェアは警告効果を表示する必要があります。例えば、フレームの端が赤くなるような、高徳地図のような警告効果です。

続きを読む
同じカテゴリ / 同じタグ 2024/06/20

CodeWF.EventBus:軽量イベントバス、コミュニケーションをよりスムーズに

CodeWF.EventBusは、モジュール間の疎結合通信を実現する柔軟なイベントバスライブラリです。WPF、WinForms、ASP.NET Coreなど、さまざまな.NETプロジェクトタイプに対応しています。シンプルな設計で、コマンドのパブリッシュとサブスクライブ、リクエストとレスポンスを簡単に実装できます。順序付けられたイベント処理により、イベントが適切に処理されることを保証します。コードを簡素化し、システムの保守性を向上させます。

続きを読む