.NET 8でSPREAD for WPFを使う方法を解説!

WPFスプレッドシートコンポーネント「SPREAD for WPF(スプレッド)」は、2024年4月にリリースされたバージョン「4.0J SP1」から .NETの最新バージョン「 .NET 8」環境に対応しています。

本記事では、SPREAD for WPFに含まれているGcSpreadGridコントロールとGcSpreadSheetコントロールそれぞれを .NET 8で使うときの具体的な手順をご紹介します。また、それぞれのコントロールの特長的な機能である「1レコード複数行」と「アウトライン行列」を実装する方法についても解説します。

はじめに

本記事では .NET 8に対応しているVisual Studio 2022を使用します。また、SPREADの .NET 8対応モジュールはNuGetパッケージで提供しているので、 .NET Framework版のSPREADとは少しだけ手順が異なります。

なお、ここではGcSpreadGridコントロールを例にして説明しますが、GcSpreadSheetコントロールでも同じ手順になります。

開発環境

SPREADのNuGetパッケージをプロジェクトに追加するには、GcSpreadGridGcSpreadSheetのヘルプでも解説しているように、コードを記述してSPREADをウィンドウに追加する方法とUI操作でSPREADをツールボックスからウィンドウに追加する方法の2つがありますが、ここでは、UI操作を使う方法をご紹介します。

.NET 8でのGcSpreadGridの使用方法

まずはSPREAD for WPFが販売開始当初から提供しているGcSpreadGridコントロールを .NET 8環境で利用する手順を紹介します。また、GcSpreadGridコントロールの特長的な機能である「1レコード複数行」の機能を実装する方法についても解説します。

新規プロジェクトの作成

最初に、Visual Studio 2022を起動して「新しいプロジェクトの作成」を押下します。

新しいプロジェクトの作成

次に「新しいプロジェクトの作成」画面で「C#」+「Windows」+「デスクトップ」でフィルタし、「WPF アプリケーション」を選択し、[次へ]ボタンを押下して次の画面へ移動します。

プロジェクトテンプレートの選択

「新しいプロジェクトを構成します」画面では「プロジェクト名」を設定します。名称は任意ですが、ここでは「SpreadGrid_net8」にします。

「プロジェクト名」を設定したら[次へ]ボタンを押下します。

プロジェクト名の設定

「追加情報」画面では、「フレームワーク」が「 .NET 8.0 (長期的なサポート)」になっているのを確認して[作成]ボタンを押下します。これで、新しいプロジェクトが作成されます。

フレームワークの選択

NuGetパッケージをプロジェクトに追加する

作成したプロジェクトで .NET 8.0対応版のSPREAD(GcSpreadGrid)を使用するには、以下のNuGetパッケージをプロジェクトに追加する必要があります。

ソリューションエクスプローラーで「SpreadGrid_net8」-「依存関係」を展開して「NuGetパッケージの管理」を押下します。

NuGetパッケージの管理

表示された「NuGetパッケージマネージャー」の「参照」タブで「GrapeCity.Wpf.SpreadGrid.ja」をキーワードにして検索すると下のような画面になるので、右側の[インストール]ボタンを押下します。

GcSpreadGridのNuGetパッケージ

「変更のプレビュー」ダイアログが表示されたら[適用]ボタンをクリックします。

変更のプレビュー

続いて「ライセンスへの同意」 ダイアログで[同意する] ボタンをクリックすると、SPREADのNuGetパッケージがプロジェクトに追加されます。

ライセンスへの同意

ウィンドウにコントロールを追加する

ウィンドウのデザイン画面でツールボックスを開くと、「GcSpreadGrid」という項目が追加されているので、GcSpreadGridをダブルクリックしてGcSpreadGridコントロールを配置します。

コントロールの追加

ソリューションエクスプローラーで「依存関係」-「パッケージ」を開いて内容を確認すると、「GrapeCity.Wpf.SpreadGrid.ja (4.1.0)」の「コンパイル時のアセンブリ」として下のようなコンポーネントが登録されていることが分かります。

追加されたコンポーネント

これらのアセンブリは、次のような「\.nuget\packages」フォルダに収められています。

C:\Users\ユーザー名\.nuget\packages\grapecity.wpf.spreadgrid.ja\4.1.0\lib\net6.0-windows7.0\

「1レコード複数行」の機能を使ってみる

続いて、GcSpreadGridコントロールの「1レコード複数行」の機能を実装しましょう。1レコード複数行の詳細については製品ヘルプを参照してください。

また、以下からダウンロードできるGcSpreadGridのデモの「1レコード複数行」-「ベーシック」、および製品に付属しているサンプル「GcSpreadGrid_2022_NET6.sln」の「\GcSpreadGrid\Pages\MultiRow\uMultiRowB.xaml.cs」でも紹介しているので、こちらもご参考にしてください。

以下では、1レコードを2行で表示し、その際にセルを行方向に連結する部分と列方向に連結する部分ができるようにレイアウトを設定する例を紹介します。列ヘッダと明細部のレイアウトを個別に設定することもできますが、ここでは、列ヘッダにも明細部のレイアウトを使うことにします。

完成すると次のようになります。

1レコード複数行

データの作成

最初に、GcSpreadGridコントロールに連結するデータを作成しましょう。

プロジェクトに「Data.cs」という名称のクラスファイルを追加して、下記のように記述します。

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

namespace SpreadGrid_net8
{
    public class Sale : INotifyPropertyChanged
    {
        string? code;
        [Display(ShortName = "コード")]
        public string? Code
        {
            set { code = value; NotifyPropertyChanged(nameof(Code)); }
            get => code;
        }

        string? name;
        [Display(ShortName = "名称")]
        public string? Name
        {
            set { name = value; NotifyPropertyChanged(nameof(Name)); }
            get => name;
        }

        int? price1;
        [Display(ShortName = "仕入単価")]
        public int? Price1
        {
            set { price1 = value; NotifyPropertyChanged(nameof(Price1)); }
            get => price1;
        }

        int? price2;
        [Display(ShortName = "売上単価")]
        public int? Price2
        {
            set { price2 = value; NotifyPropertyChanged(nameof(Price2)); }
            get => price2;
        }

        int? quantity;
        [Display(ShortName = "数量")]
        public int? Quantity
        {
            set { quantity = value; NotifyPropertyChanged(nameof(Quantity)); }
            get => quantity;
        }

        public event PropertyChangedEventHandler? PropertyChanged;
        protected void NotifyPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this,
                new PropertyChangedEventArgs(propertyName));
        }
    }

    public class SaleCollection : ObservableCollection<Sale>
    {
        public SaleCollection()
        {
            Add(new Sale { Code = "A001", Name = "えごま", 
                Price1 = 120, Price2 = 240, Quantity = 100 });
            Add(new Sale { Code = "A002", Name = "グレープシード",
                Price1 = 120, Price2 = 280, Quantity = 100 });
            Add(new Sale { Code = "B001", Name = "ウォールナッツ",
                Price1 = 1000, Price2 = 2400, Quantity = 50 });
            Add(new Sale { Code = "B002", Name = "ココナッツ", 
                Price1 = 4000, Price2 = 7000, Quantity = 60 });
            Add(new Sale { Code = "B003", Name = "スイートアーモンド", 
                Price1 = 90, Price2 = 180, Quantity = 2000 });
            Add(new Sale { Code = "C001", Name = "オリーブ", 
                Price1 = 2000, Price2 = 4000, Quantity = 100 });
            Add(new Sale { Code = "C002", Name = "ビーワックス", 
                Price1 = 1500, Price2 = 3200, Quantity = 80 });
            Add(new Sale { Code = "C003", Name = "馬油", 
                Price1 = 3200, Price2 = 7000, Quantity = 60 });
        }
    }
}

GcSpreadGridコントロールには、上記のデータに加えて「Sales(売上)」と「Profit(粗利)」という項目がありますが、これらは他の項目を使って算出できるので、データには含めていません。

GcSpreadGridコントロールをデータ連結する方法について製品ヘルプで詳しく解説しているので、そちらもご一読いただければと思います。

XAMLの設定

1レコード複数行の設定は、製品ヘルプで解説しているようにXAMLで設定する方法と、コードで設定する方法があります。ここではWPF製品らしくXAMLで設定します。

「MainWindow.xaml」ファイル全体の記述は次のようになります。この内、ハイライトした箇所がデータ連結に関連した部分です。

<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:SpreadGrid_net8"
        xmlns:sg="http://schemas.grapecity.com/windows/spreadgrid/2012"
        d:DataContext="{d:DesignInstance Type=local:SaleCollection}"
        x:Class="SpreadGrid_net8.MainWindow"
        mc:Ignorable="d"
        Title="MainWindow" Height="420" Width="600" 
        WindowStartupLocation="CenterScreen">
    <Window.Resources>
        <local:SaleCollection x:Key="SaleCollection"/>
    </Window.Resources>
    <Grid>
        <sg:GcSpreadGrid x:Name="GcSpreadGrid" 
                         AutoGenerateColumns="False" 
                         ItemsSource="{DynamicResource SaleCollection}" 
                         LayoutMode="Template">
            <sg:GcSpreadGrid.Columns>
                <sg:Column Locked="True">
                    <sg:Column.DataField>
                        <sg:BindingDataField Binding="{Binding Code}"/>
                    </sg:Column.DataField>
                </sg:Column>
                <sg:Column Locked="True" Background="Khaki">
                    <sg:Column.DataField>
                        <sg:BindingDataField Binding="{Binding Name}"/>
                    </sg:Column.DataField>
                </sg:Column>
                <sg:Column>
                    <sg:Column.DataField>
                        <sg:BindingDataField Binding="{Binding Price1}"/>
                    </sg:Column.DataField>
                    <sg:Column.CellType>
                        <sg:GeneralCellType FormatString="#,##0 円"/>
                    </sg:Column.CellType>
                </sg:Column>
                <sg:Column>
                    <sg:Column.DataField>
                        <sg:BindingDataField Binding="{Binding Price2}"/>
                    </sg:Column.DataField>
                    <sg:Column.CellType>
                        <sg:GeneralCellType FormatString="#,##0 円"/>
                    </sg:Column.CellType>
                </sg:Column>
                <sg:Column>
                    <sg:Column.DataField>
                        <sg:BindingDataField Binding="{Binding Quantity}"/>
                    </sg:Column.DataField>
                    <sg:Column.CellType>
                        <sg:GeneralCellType FormatString="#,##0"/>
                    </sg:Column.CellType>
                </sg:Column>
                <sg:Column Name="Sales" 
                           Locked="True" 
                           Header="売上" 
                           Foreground="Blue"
                           Formula="Price2*Quantity">
                    <sg:Column.CellType>
                        <sg:GeneralCellType FormatString="#,##0 円"/>
                    </sg:Column.CellType>
                </sg:Column>
                <sg:Column Name="Profit" 
                           Locked="True" 
                           Header="粗利"
                           Formula="(Price2 - Price1)*Quantity">
                    <sg:Column.CellType>
                        <sg:GeneralCellType FormatString="#,##0 円"/>
                    </sg:Column.CellType>
                </sg:Column>
            </sg:GcSpreadGrid.Columns>
            <sg:GcSpreadGrid.LayoutTemplate>
                <sg:LayoutTemplate>
                    <sg:LayoutTemplate.ColumnDefinitions>
                        <sg:TemplateColumnDefinition Width="90"/>
                        <sg:TemplateColumnDefinition Width="90"/>
                        <sg:TemplateColumnDefinition Width="90"/>
                        <sg:TemplateColumnDefinition Width="90"/>
                        <sg:TemplateColumnDefinition Width="100"/>
                    </sg:LayoutTemplate.ColumnDefinitions>
                    <sg:LayoutTemplate.RowTemplate>
                        <sg:RowTemplate>
                            <sg:RowTemplate.RowDefinitions>
                                <sg:TemplateRowDefinition Height="20"/>
                                <sg:TemplateRowDefinition Height="20"/>
                            </sg:RowTemplate.RowDefinitions>
                            <sg:RowTemplate.Cells>
                                <sg:CellTemplate RowIndex="0" 
                                                 ColumnIndex="0" 
                                                 DataColumnName="Code" 
                                                 RowSpan="2"/>
                                <sg:CellTemplate RowIndex="0" 
                                                 ColumnIndex="1" 
                                                 DataColumnName="Name" 
                                                 ColumnSpan="2"/>
                                <sg:CellTemplate RowIndex="0" 
                                                 ColumnIndex="3" 
                                                 DataColumnName="Quantity" 
                                                 RowSpan="2"/>
                                <sg:CellTemplate RowIndex="0" 
                                                 ColumnIndex="4" 
                                                 DataColumnName="Sales"/>
                                <sg:CellTemplate RowIndex="1" 
                                                 ColumnIndex="1" 
                                                 DataColumnName="Price1"/>
                                <sg:CellTemplate RowIndex="1" 
                                                 ColumnIndex="2" 
                                                 DataColumnName="Price2"/>
                                <sg:CellTemplate RowIndex="1" 
                                                 ColumnIndex="4" 
                                                 DataColumnName="Profit"/>
                            </sg:RowTemplate.Cells>
                        </sg:RowTemplate>
                    </sg:LayoutTemplate.RowTemplate>
                </sg:LayoutTemplate>
            </sg:GcSpreadGrid.LayoutTemplate>
        </sg:GcSpreadGrid>
    </Grid>
</Window>

GcSpreadGridコントロールで設定しているのは、下記の3つのプロパティだけです。

・・・(中略)・・・
        <sg:GcSpreadGrid x:Name="GcSpreadGrid" 
                         AutoGenerateColumns="False" 
                         ItemsSource="{DynamicResource SaleCollection}" 
                         LayoutMode="Template">

・・・(中略)・・・
プロパティ内容
AutoGenerateColumns「False」に設定(データ連結時の列自動生成を停止)
ItemsSourceData.cs内のSaleCollectionクラスを参照
LayoutMode「Template」に設定(レイアウトテンプレートを利用)

列に関する設定は<sg:GcSpreadGrid.Columns>タグで行います。また、「1レコード複数行」を実現するためのレイアウトテンプレートは<sg:LayoutTemplate.RowTemplate>タグで設定します。

なお、「Sales(売上)」と「Profit(粗利)」の2つの非連結列については、下記のようにColumnクラスのFormulaプロパティに数式を設定して連結データから算出しています。

・・・(中略)・・・
                <sg:Column Name="Sales" 
                           ・・・(中略)・・・
                           Formula="Price2*Quantity">
                           ・・・(中略)・・・
                </sg:Column>
                <sg:Column Name="Profit" 
                           ・・・(中略)・・・
                           Formula="(Price2 - Price1)*Quantity">
                           ・・・(中略)・・・
                </sg:Column>
・・・(中略)・・・

.NET 8でのGcSpreadSheetの使用方法

ここではバージョン「3.0J」で追加されたGcSpreadSheetコントロールを .NET 8環境で利用する手順を紹介します。また、GcSpreadSheetコントロールの特長的な機能である「アウトライン行列」を実装する方法についても解説します。

新規プロジェクトの作成

最初に、Visual Studio 2022を起動して「新しいプロジェクトの作成」を押下します。

新しいプロジェクトの作成

次に「新しいプロジェクトの作成」画面で「C#」+「Windows」+「デスクトップ」でフィルタし、「WPF アプリケーション」を選択し、[次へ]ボタンを押下して次の画面へ移動します。

プロジェクトテンプレートの選択

「新しいプロジェクトを構成します」画面では「プロジェクト名」を設定します。名称は任意ですが、ここでは「SpreadSheet_net8」にします。

「プロジェクト名」を設定したら[次へ]ボタンを押下します。

プロジェクト名の設定

「追加情報」画面では、「フレームワーク」が「 .NET 8.0 (長期的なサポート)」になっているのを確認して[作成]ボタンを押下します。これで、新しいプロジェクトが作成されます。

フレームワークの選択

NuGetパッケージをプロジェクトに追加する

作成したプロジェクトで .NET 8.0対応版のSPREAD(GcSpreadSheet)を使用するには以下のNuGetパッケージをプロジェクトに追加する必要があります。

ソリューションエクスプローラーで「SpreadSheet_net8」-「依存関係」を展開して[NuGetパッケージの管理]を押下します。

NuGetパッケージの管理

表示された「NuGetパッケージマネージャー」の「参照」タブで「GrapeCity.Wpf. SpreadSheet.ja」をキーワードにして検索すると下のような画面になるので、右側の[インストール]ボタンを押下します。

GcSpreadSheetのNuGetパッケージ

「変更のプレビュー」ダイアログが表示されたら[適用]ボタンをクリックします。

変更のプレビュー

続いて「ライセンスへの同意」 ダイアログで[同意する] ボタンをクリックすると、SPREADのNuGetパッケージがプロジェクトに追加されます。

ライセンスへの同意

ウィンドウにコントロールを追加する

ウィンドウのデザイン画面でツールボックスを開くと、次のような2つの項目が追加されます。

  • GcFormulaBar
  • GcSpreadSheet

ここでは、GcSpreadSheetをダブルクリックしてGcSpreadSheetコントロールをウィンドウに配置します。

コントロールの追加

ソリューションエクスプローラーで「依存関係」-「パッケージ」を開いて内容を確認すると、「GrapeCity.Wpf.SpreadSheet.ja (4.1.0)」の「コンパイル時のアセンブリ」として下のようなコンポーネントが登録されていることが分かります。

追加されたコンポーネント

これらのアセンブリは、次のような「\.nuget\packages」フォルダに収められています。

C:\Users\ユーザー名\.nuget\packages\grapecity.wpf.spreadsheet.ja\4.1.0\lib\net6.0-windows7.0\

「アウトライン行列」を使ってみる

GcSpreadSheetコントロールには多くの機能が含まれていますが、ここでは「アウトライン行列」について解説します。アウトライン行列については製品ヘルプもご一読いただければと思います。

また、以下からダウンロードできるGcSpreadSheetのデモの「シート」-「アウトライン」、および製品に付属しているサンプル「GcSpreadSheet_2022_NET6.sln」の「\GcSpreadSheet\Pages\Sheet\uSheetOutline.xaml.cs」でも紹介しているので、こちらもご参考にしてください。

アウトライン行とアウトライン列を設定したシートを操作すると次のようになります。この機能により、その時点で必要な情報だけに絞り込んで表示することが可能になります。

コードの記述

「MainWindow.xaml」ファイルについては、コントロールをウィンドウに配置した状態から変更する箇所はありません。アウトライン行列は、「MainWindow.xaml.cs」ファイルにコードを記述して実現します。

記述する内容は、次のようになります。

using GrapeCity.Wpf.SpreadSheet;
using System.Windows;

namespace SpreadSheet_net8
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            // シートの設定
            var sheet = GcSpreadSheet.Workbook.ActiveSheet;
            sheet.ColumnCount = 10;
            sheet.RowCount = 100;
            SetData(sheet);
            SetOutline(sheet);
        }

        public void SetData(GrapeCity.Spreadsheet.IWorksheet sheet)
        {
            var baseData = new[] 
            { 
                "a1", "a2", "A", "b1", "b2", "B", "AB", "c1", "c2", "C"
            };

            // 列ヘッダの設定
            for (var i = 0; i < sheet.ColumnCount; i++)
            {
                sheet.ColumnHeader.Cells[i].Value = baseData[i];
            }

            // 値の設定
            for (var i = 0; i < sheet.RowCount; i++)
            {
                for (var j = 0; j < sheet.ColumnCount; j++)
                {
                    sheet.SetValue(i, j, $"{baseData[j]}_{i + 1}");
                }
            }
        }

        public void SetOutline(GrapeCity.Spreadsheet.IWorksheet sheet)
        {
            // アウトライン行の設定
            for (var i = 0; i < 10; i++)
            {
                sheet.Range($"{(i * 10) + 1}:{(i * 10) + 9}").Group();
            }

            // アウトライン列の設定
            sheet.Range("A:F").Group();
            sheet.Range("A:B").Group();
            sheet.Range("D:E").Group();
            sheet.Range("H:I").Group();
        }
    }
}

アウトラインは、GrapeCity.Spreadsheet.IWorksheetインタフェースのRangeメソッドとGrapeCity.Spreadsheet.IRange インタフェースのGroupメソッドを使って実現します。

Rangeメソッドの引数には範囲を指定する文字列を設定しますが、アウトライン行の場合には「Range("1:9")」のように行番号(基数=1)で指定し、アウトライン列のときには「Range("A:F")」のように列を表すアルファベット(第1列がA)で指定します。

実行時にアウトラインのレベルボタンをクリックすることで、そのレベルのすべてのアウトラインを折りたたむことができます。すべてのアウトラインを展開するには、1つ下のレベルのレベルボタンをクリックします。この様子は、この項目の前述の動画でもご確認いただけます。

さいごに

今回ご紹介したように .NET 8でも .NET Frameworkとほとんど同じようにSPREAD for WPFを使うことができます。この記事が、新しいプラットフォームである .NET 8でSPREADをご利用いただくきっかけになれば幸いです。

Webサイトでは製品の機能を手軽に体験できるデモアプリケーションやトライアル版も公開しておりますので、こちらもご確認ください。

また、ご導入前の製品に関するご相談、ご導入後の各種サービスに関するご質問など、お気軽にお問合せください。

\  この記事をシェアする  /