FlexGrid for WPF
Excelファイルを保存する
基本操作 > エクスポート > Excelファイルを保存する

C1FlexGrid の内容は、デフォルトで CSV、HTML形式またはプレーンテキストとしてエクスポートできますが、C1Excel を使用してグリッドのデータをExcel 形式にエクスポートすることも可能です。また、C1Excel ライブラリを使用してエクセル(XLSX形式)にもエクスポートできます。

次の例では、通常の連結グリッド C1FlexGrid に対して ExcelFilter のヘルパークラスを使用してグリッドの内容を XLSX 形式ファイルにエクスポートする方法を示します。基本的に、これらのヘルパークラスをプロジェクトに追加してクラスのメソッドを使用することでデータをエクセルファイルにエクスポートできます。

 

[実行例]

[Excelファイルを保存する]

 

 サンプルコードは次のようになります。

 

コードのコピー
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        IEnumerable<Product> products = Product.GetProducts(250);
        products.ElementAt(0).Price = -10;
        products.ElementAt(1).Price = -10;

        C1FlexGrid1.ItemsSource = products;
      
       
    }

    private void btnExport_Click(object sender, RoutedEventArgs e)
    {
        var dlg = new Microsoft.Win32.SaveFileDialog();
        dlg.DefaultExt = "xlsx";
        dlg.Filter = "Excel Workbook (*.xlsx)|*.xlsx|" + "HTML File (*.htm;*.html)|*.htm;*.html|" + "Comma Separated Values (*.csv)|*.csv|" + "Text File (*.txt)|*.txt";
        if (dlg.ShowDialog() == true)
        {
            var ext = System.IO.Path.GetExtension(dlg.SafeFileName).ToLower();
            ext = ext == ".htm" ? "ehtm" : ext == ".html" ? "ehtm" : ext;
            switch (ext)
            {
                case "ehtm":
                    {
                        C1FlexGrid1.Save(dlg.FileName, C1.WPF.FlexGrid.FileFormat.Html, SaveOptions.Formatted);
                        break;
                    }
                case ".csv":
                    {
                        C1FlexGrid1.Save(dlg.FileName, C1.WPF.FlexGrid.FileFormat.Csv, SaveOptions.Formatted);
                        break;
                    }
                case ".txt":
                    {
                        C1FlexGrid1.Save(dlg.FileName, C1.WPF.FlexGrid.FileFormat.Text, SaveOptions.Formatted);
                        break;
                    }
                default:
                    {
                        Save(dlg.FileName,C1FlexGrid1);
                        break;
                    }
            }
        }
    }

    public void Save(string filename, C1FlexGrid flexgrid)
    {
        // 保存するエクセルブックを作成します
        var book = new C1XLBook();
        book.Sheets.Clear();
        var  xlSheet = book.Sheets.Add("Sheet1");
        ExcelExport.ExcelFilter.Save(flexgrid, xlSheet);


        // エクセルブックを保存します
        book.Save(filename, C1.WPF.Excel.FileFormat.OpenXml);
    }
}
コードのコピー
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using C1.WPF.Excel;
using C1.WPF.FlexGrid;
using C1.WPF;

using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace ExcelExport
{

    /// <summary>
    /// XLSheetとC1FlexGridの間にデータを転送するための方法を提供するクラス
    /// </summary>
    internal sealed class ExcelFilter
    {
        private static C1XLBook _lastBook;
        private static Dictionary<XLStyle, ExcelCellStyle> _cellStyles = new Dictionary<XLStyle, ExcelCellStyle>();

        private static Dictionary<ExcelCellStyle, XLStyle> _excelStyles = new Dictionary<ExcelCellStyle, XLStyle>();
        //---------------------------------------------------------------------------------
        #region "** object model"

        /// <summary>
        /// C1FlexGridのコンテンツをXLSheetに保存します
        /// </summary>
        public static void Save(C1FlexGrid flex, XLSheet sheet)
        {
            // 新しいbookの場合は、スタイルのキャッシュをクリアします
            if (!object.ReferenceEquals(sheet.Book, _lastBook))
            {
                _cellStyles.Clear();
                _excelStyles.Clear();
                _lastBook = sheet.Book;
            }

            // グローバルパラメーターを保存します
            sheet.DefaultRowHeight = PixelsToTwips(flex.Rows.DefaultSize);
            sheet.DefaultColumnWidth = PixelsToTwips(flex.Columns.DefaultSize);
            sheet.Locked = flex.IsReadOnly;
            sheet.ShowGridLines = flex.GridLinesVisibility != GridLinesVisibility.None;
            sheet.ShowHeaders = flex.HeadersVisibility != HeadersVisibility.None;
            sheet.OutlinesBelow = flex.GroupRowPosition == GroupRowPosition.BelowData;

            // 列を保存します
            sheet.Columns.Clear();
            foreach (Column col in flex.Columns)
            {
                dynamic c = sheet.Columns.Add();
                if (!col.Width.IsAuto)
                {
                    c.Width = PixelsToTwips(col.ActualWidth);
                }
                c.Visible = col.Visible;
                if (col.CellStyle is ExcelCellStyle)
                {
                    c.Style = GetXLStyle(flex, sheet, (ExcelCellStyle)col.CellStyle);
                }
            }

            sheet.Rows.Clear();

            // 列ヘッダーを保存します
            XLStyle headerStyle = default(XLStyle);
            headerStyle = new XLStyle(sheet.Book);
            headerStyle.Font = new XLFont("Arial", 10, true, false);

            foreach (Row row in flex.ColumnHeaders.Rows)
            {
                dynamic r = sheet.Rows.Add();
                if (row.Height > -1)
                {
                    r.Height = PixelsToTwips(row.Height);
                }
                if (row.CellStyle is ExcelCellStyle)
                {
                    r.Style = GetXLStyle(flex, sheet, (ExcelCellStyle)row.CellStyle);
                }
                if (row is ExcelRow)
                {
                    r.OutlineLevel = ((ExcelRow)row).Level;
                }
                for (int c = 0; c <= flex.ColumnHeaders.Columns.Count - 1; c++)
                {
                    // セル値を保存します
                    dynamic cell = sheet[row.Index, c];
                    string colHeader = flex.ColumnHeaders[row.Index, c] != null ? flex.ColumnHeaders[row.Index, c].ToString() : flex.Columns[c].ColumnName;
                    cell.Value = colHeader;

                    // 列ヘッダーを太字にします
                    cell.Style = headerStyle;

                }
                r.Visible = row.Visible;
            }



            // 行を保存します
            foreach (Row row in flex.Rows)
            {
                dynamic r = sheet.Rows.Add();
                if (row.Height > -1)
                {
                    r.Height = PixelsToTwips(row.Height);
                }
                if (row.CellStyle is ExcelCellStyle)
                {
                    r.Style = GetXLStyle(flex, sheet, (ExcelCellStyle)row.CellStyle);
                }
                if (row is ExcelRow)
                {
                    r.OutlineLevel = ((ExcelRow)row).Level;
                }
                r.Visible = row.Visible;
            }

            // セルを保存します
            for (int r = flex.ColumnHeaders.Rows.Count - 1; r <= flex.Rows.Count - 1; r++)  
            {
                for (int c = 0; c <= flex.Columns.Count - 1; c++)
                {
                    // セル値を保存します
                    dynamic cell = sheet[r + 1, c];                        
                    dynamic obj = flex[r, c];
                    cell.Value = obj is FrameworkElement ? 0 : obj;

                    // セルの数式とスタイルを保存します
                    dynamic row = flex.Rows[r] as ExcelRow;
                    if (row != null)
                    {
                        // セルの数式を保存します
                        dynamic col = flex.Columns[c];

                        // セルのスタイルを保存します
                        dynamic cs = row.GetCellStyle(col) as ExcelCellStyle;
                        if (cs != null)
                        {
                            cell.Style = GetXLStyle(flex, sheet, cs);
                        }
                    }
                }
            }

            // 選択範囲を保存します
            dynamic sel = flex.Selection;
            if (sel.IsValid)
            {
                dynamic xlSel = new XLCellRange(sheet, sel.Row, sel.Row2, sel.Column, sel.Column2);
                sheet.SelectedCells.Clear();
                sheet.SelectedCells.Add(xlSel);
            }
        }

        #endregion

        //---------------------------------------------------------------------------------
        #region "** implementation"

        private static double TwipsToPixels(double twips)
        {
            return Convert.ToInt32(twips / 1440.0 * 96.0 * 1.2 + 0.5);
        }
        private static int PixelsToTwips(double pixels)
        {
            return Convert.ToInt32(pixels * 1440.0 / 96.0 / 1.2 + 0.5);
        }
        private static double PointsToPixels(double points)
        {
            return points / 72.0 * 96.0 * 1.2;
        }
        private static double PixelsToPoints(double pixels)
        {
            return pixels * 72.0 / 96.0 / 1.2;
        }

        // Excelスタイルをクリッドスタイルに変更します
        private static ExcelCellStyle GetCellStyle(XLStyle x)
        {
            // キャッシュを検索します
            ExcelCellStyle s = default(ExcelCellStyle);
            if (_cellStyles.TryGetValue(x, out s))
            {
                return s;
            }

            // 見つかりません。スタイルを作成します
            s = new ExcelCellStyle();

            // 配置
            switch (x.AlignHorz)
            {
                case XLAlignHorzEnum.Left:
                    s.HorizontalAlignment = HorizontalAlignment.Left;
                    break;
                case XLAlignHorzEnum.Center:
                    s.HorizontalAlignment = HorizontalAlignment.Center;
                    break;
                case XLAlignHorzEnum.Right:
                    s.HorizontalAlignment = HorizontalAlignment.Right;
                    break;
            }
            switch (x.AlignVert)
            {
                case XLAlignVertEnum.Top:
                    s.VerticalAlignment = VerticalAlignment.Top;
                    break;
                case XLAlignVertEnum.Center:
                    s.VerticalAlignment = VerticalAlignment.Center;
                    break;
                case XLAlignVertEnum.Bottom:
                    s.VerticalAlignment = VerticalAlignment.Bottom;
                    break;
            }
            s.TextWrapping = x.WordWrap;

            // カラー
            if (x.BackPattern == XLPatternEnum.Solid && IsColorValid(x.BackColor))
            {
                s.Background = new SolidColorBrush(x.BackColor);
            }
            if (IsColorValid(x.ForeColor))
            {
                s.Foreground = new SolidColorBrush(x.ForeColor);
            }

            // フォント
            dynamic font = x.Font;
            if (font != null)
            {
                s.FontFamily = new FontFamily(font.FontName);
                s.FontSize = PointsToPixels(font.FontSize);
                if (font.Bold)
                {
                    s.FontWeight = FontWeights.Bold;
                }
                if (font.Italic)
                {
                    s.FontStyle = FontStyles.Italic;
                }
                if (font.Underline != XLUnderlineStyle.None)
                {
                    s.TextDecorations = TextDecorations.Underline;
                }
            }

            // 書式
            if (!string.IsNullOrEmpty(x.Format))
            {
                s.Format = XLStyle.FormatXLToDotNet(x.Format);
            }

            // 境界線
            s.CellBorderThickness = new Thickness(GetBorderThickness(x.BorderLeft), GetBorderThickness(x.BorderTop), GetBorderThickness(x.BorderRight), GetBorderThickness(x.BorderBottom));
            s.CellBorderBrushLeft = GetBorderBrush(x.BorderColorLeft);
            s.CellBorderBrushTop = GetBorderBrush(x.BorderColorTop);
            s.CellBorderBrushRight = GetBorderBrush(x.BorderColorRight);
            s.CellBorderBrushBottom = GetBorderBrush(x.BorderColorBottom);

            // キャッシュに保存して戻します
            _cellStyles[x] = s;
            return s;
        }

        // グリッドスタイルをExcelスタイルに変更します
        private static XLStyle GetXLStyle(C1FlexGrid flex, XLSheet sheet, ExcelCellStyle s)
        {
            // キャッシュで検索します
            XLStyle x = default(XLStyle);
            if (_excelStyles.TryGetValue(s,out  x))
            {
                return x;
            }

            // 見つかりません。スタイルを作成します
            x = new XLStyle(sheet.Book);

            // 配置
            if (s.HorizontalAlignment.HasValue)
            {
                switch (s.HorizontalAlignment.Value)
                {
                    case HorizontalAlignment.Left:
                        x.AlignHorz = XLAlignHorzEnum.Left;
                        break;
                    case HorizontalAlignment.Center:
                        x.AlignHorz = XLAlignHorzEnum.Center;
                        break;
                    case HorizontalAlignment.Right:
                        x.AlignHorz = XLAlignHorzEnum.Right;
                        break;
                }
            }
            if (s.VerticalAlignment.HasValue)
            {
                switch (s.VerticalAlignment.Value)
                {
                    case VerticalAlignment.Top:
                        x.AlignVert = XLAlignVertEnum.Top;
                        break;
                    case VerticalAlignment.Center:
                        x.AlignVert = XLAlignVertEnum.Center;
                        break;
                    case VerticalAlignment.Bottom:
                        x.AlignVert = XLAlignVertEnum.Bottom;
                        break;
                }
            }
            if (s.TextWrapping.HasValue)
            {
                x.WordWrap = s.TextWrapping.Value;
            }

            // カラー
            if (s.Background is SolidColorBrush)
            {
                x.BackColor = ((SolidColorBrush)s.Background).Color;
                x.BackPattern = XLPatternEnum.Solid;
            }
            if (s.Foreground is SolidColorBrush)
            {
                x.ForeColor = ((SolidColorBrush)s.Foreground).Color;
            }

            // フォント
            dynamic fontName = flex.FontFamily.Source;
            dynamic fontSize = flex.FontSize;
            dynamic bold = false;
            dynamic italic = false;
            bool underline = false;
            bool hasFont = false;
            if (s.FontFamily != null)
            {
                fontName = s.FontFamily.Source;
                hasFont = true;
            }
            if (s.FontSize.HasValue)
            {
                fontSize = s.FontSize.Value;
                hasFont = true;
            }
            if (s.FontWeight.HasValue)
            {
                bold = s.FontWeight.Value == FontWeights.Bold || s.FontWeight.Value == FontWeights.ExtraBold || s.FontWeight.Value == FontWeights.SemiBold;
                hasFont = true;
            }
            if (s.FontStyle.HasValue)
            {
                italic = s.FontStyle.Value == FontStyles.Italic;
                hasFont = true;
            }
            if (s.TextDecorations != null)
            {
                underline = true;
                hasFont = true;
            }
            if (hasFont)
            {
                fontSize = PixelsToPoints(fontSize);
                if (underline)
                {
                    dynamic color = Colors.Black;
                    if (flex.Foreground is SolidColorBrush)
                    {
                        color = ((SolidColorBrush)flex.Foreground).Color;
                    }
                    if (s.Foreground is SolidColorBrush)
                    {
                        color = ((SolidColorBrush)s.Foreground).Color;
                    }
                    x.Font = new XLFont(fontName, Convert.ToSingle(fontSize), bold, italic, false, XLFontScript.None, XLUnderlineStyle.Single, color);
                }
                else
                {
                    x.Font = new XLFont(fontName, Convert.ToSingle(fontSize), bold, italic);
                }
            }

            // 書式
            if (!string.IsNullOrEmpty(s.Format))
            {
                x.Format = XLStyle.FormatDotNetToXL(s.Format);
            }

            // 境界線
            if (s.CellBorderThickness.Left > 0 && s.CellBorderBrushLeft is SolidColorBrush)
            {
                x.BorderLeft = GetBorderLineStyle(s.CellBorderThickness.Left);
                x.BorderColorLeft = ((SolidColorBrush)s.CellBorderBrushLeft).Color;
            }
            if (s.CellBorderThickness.Top > 0 && s.CellBorderBrushTop is SolidColorBrush)
            {
                x.BorderTop = GetBorderLineStyle(s.CellBorderThickness.Top);
                x.BorderColorTop = ((SolidColorBrush)s.CellBorderBrushTop).Color;
            }
            if (s.CellBorderThickness.Right > 0 && s.CellBorderBrushRight is SolidColorBrush)
            {
                x.BorderRight = GetBorderLineStyle(s.CellBorderThickness.Right);
                x.BorderColorRight = ((SolidColorBrush)s.CellBorderBrushRight).Color;
            }
            if (s.CellBorderThickness.Bottom > 0 && s.CellBorderBrushBottom is SolidColorBrush)
            {
                x.BorderBottom = GetBorderLineStyle(s.CellBorderThickness.Bottom);
                x.BorderColorBottom = ((SolidColorBrush)s.CellBorderBrushBottom).Color;
            }

            // キャッシュに保存して返します
            _excelStyles[s] = x;
            return x;
        }
        private static double GetBorderThickness(XLLineStyleEnum ls)
        {
            switch (ls)
            {
                case XLLineStyleEnum.None:
                    return 0;
                case XLLineStyleEnum.Hair:
                    return 0.5;
                case XLLineStyleEnum.Thin:
                case XLLineStyleEnum.ThinDashDotDotted:
                case XLLineStyleEnum.ThinDashDotted:
                case XLLineStyleEnum.Dashed:
                case XLLineStyleEnum.Dotted:
                    return 1;
                case XLLineStyleEnum.Medium:
                case XLLineStyleEnum.MediumDashDotDotted:
                case XLLineStyleEnum.MediumDashDotted:
                case XLLineStyleEnum.MediumDashed:
                case XLLineStyleEnum.SlantedMediumDashDotted:
                    return 2;
                case XLLineStyleEnum.Double:
                case XLLineStyleEnum.Thick:
                    return 3;
            }
            return 0;
        }
        private static XLLineStyleEnum GetBorderLineStyle(double t)
        {
            if (t == 0)
            {
                return XLLineStyleEnum.None;
            }
            if (t < 1)
            {
                return XLLineStyleEnum.Hair;
            }
            if (t < 2)
            {
                return XLLineStyleEnum.Thin;
            }
            if (t < 3)
            {
                return XLLineStyleEnum.Medium;
            }
            return XLLineStyleEnum.Thick;
        }
        private static Brush GetBorderBrush(Color color)
        {
            return IsColorValid(color) ? new SolidColorBrush(color) : null;
        }
        private static bool IsColorValid(Color color)
        {
            return color.A > 0;
            // == 0xff;
        }

        #endregion
    }
}
コードのコピー
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.ComponentModel;
using C1.WPF.FlexGrid;

namespace ExcelExport
{
    /// <summary>
    /// Excelスタイルのセル境界線と書式指定文字列を提供するためのCellStyleクラスを拡張します
    /// </summary>
    public class ExcelCellStyle : CellStyle
    {
        // ** フィールド
        private string _format;
        private Thickness _bdrThickness;
        private Brush _bdrLeft;
        private Brush _bdrTop;
        private Brush _bdrRight;
        private Brush _bdrBottom;

        private static Thickness _thicknessEmpty = new Thickness(0);
        // ** オブジェクト・モデル
        public string Format
        {
            get { return _format; }
            set
            {
                if (value != _format)
                {
                    _format = value;
                    OnPropertyChanged(new PropertyChangedEventArgs("Format"));
                }
            }
        }
        public Thickness CellBorderThickness
        {
            get { return _bdrThickness; }
            set
            {
                if (value != _bdrThickness)
                {
                    _bdrThickness = value;
                    OnPropertyChanged(new PropertyChangedEventArgs("BorderThickness"));
                }
            }
        }
        public Brush CellBorderBrushLeft
        {
            get { return _bdrLeft; }
            set
            {
                if (!object.ReferenceEquals(value, _bdrLeft))
                {
                    _bdrLeft = value;
                    OnPropertyChanged(new PropertyChangedEventArgs("BorderColorLeft"));
                }
            }
        }
        public Brush CellBorderBrushTop
        {
            get { return _bdrTop; }
            set
            {
                if (!object.ReferenceEquals(value, _bdrTop))
                {
                    _bdrTop = value;
                    OnPropertyChanged(new PropertyChangedEventArgs("BorderColorTop"));
                }
            }
        }
        public Brush CellBorderBrushRight
        {
            get { return _bdrRight; }
            set
            {
                if (!object.ReferenceEquals(value, _bdrRight))
                {
                    _bdrRight = value;
                    OnPropertyChanged(new PropertyChangedEventArgs("BorderColorRight"));
                }
            }
        }
        public Brush CellBorderBrushBottom
        {
            get { return _bdrBottom; }
            set
            {
                if (!object.ReferenceEquals(value, _bdrBottom))
                {
                    _bdrBottom = value;
                    OnPropertyChanged(new PropertyChangedEventArgs("BorderColorBottom"));
                }
            }
        }

        // ** オーバーライド
        public override void Apply(Border bdr, SelectedState selState)
        {
            base.Apply(bdr, selState);
            ApplyBorder(bdr, _bdrLeft, new Thickness(_bdrThickness.Left, 0, 0, 0));
            ApplyBorder(bdr, _bdrTop, new Thickness(0, _bdrThickness.Top, 0, 0));
            ApplyBorder(bdr, _bdrRight, new Thickness(0, 0, _bdrThickness.Right, 0));
            ApplyBorder(bdr, _bdrBottom, new Thickness(0, 0, 0, _bdrThickness.Bottom));
        }
        private void ApplyBorder(Border bdr, Brush br, Thickness t)
        {
            if (br != null && t != _thicknessEmpty)
            {
                // 内部の境界線を作成します
                dynamic inner = new Border();
                inner.BorderThickness = t;
                inner.BorderBrush = br;

                // コンテンツに拡張します
                dynamic content = bdr.Child;
                bdr.Child = inner;
                inner.Child = content;

                // パディングします
                inner.Padding = bdr.Padding;
                bdr.Padding = _thicknessEmpty;
            }
        }
    }
}

コードのコピー
using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using C1.WPF.FlexGrid;
using C1.WPF.Excel;

using System.Globalization;
using System.Windows;

namespace ExcelExport
{

    /// <summary>
    /// 編集可能、ツリー ノードとして使用でき、各列と関連するセルの 
    /// スタイルのコレクションを保守するグリッド行
    /// </summary>
    public class ExcelRow : GroupRow
    {
        // ** フィールド

        private Dictionary<Column, CellStyle> _cellStyles;
        // 既定の有効桁数を6桁に設定します
        private const string DEFAULT_FORMAT = "#,##0.######";

        // ** ctor
        public ExcelRow(ExcelRow styleRow)
        {
            IsReadOnly = false;
            if (styleRow != null && styleRow.Grid != null) {
                foreach (var c in styleRow.Grid.Columns) {
                    dynamic cs = styleRow.GetCellStyle(c);
                    if (cs != null) {
                        this.SetCellStyle(c, cs.Clone());
                    }
                }
            }
        }
        public ExcelRow()
            : this(null)
        {
        }

        // ** オブジェクト・モデル

        /// <summary>
        /// データを取得する場合、書式を適用するためにオーバーライドされる
        /// </summary>
        public override string GetDataFormatted(Column col)
        {
            // データを取得します
            dynamic data = GetDataRaw(col);

            // 書式を適用します
            dynamic ifmt = data as IFormattable;
            if (ifmt != null)
            {
                // セルの書式を取得します
                dynamic s = GetCellStyle(col) as ExcelCellStyle;
                dynamic fmt = s != null && (!string.IsNullOrEmpty(s.Format)) ? s.Format : DEFAULT_FORMAT;
                data = ifmt.ToString(fmt, CultureInfo.CurrentUICulture);
            }

            // 完了
            return data != null ? data.ToString() : string.Empty;
        }

        // ** オブジェクト・モデル

        /// <summary>
        /// この行では、セルにスタイルを適用します
        /// </summary>
        public void SetCellStyle(Column col, CellStyle style)
        {
            if (!object.ReferenceEquals(style, GetCellStyle(col)))
            {
                if (_cellStyles == null)
                {
                    _cellStyles = new Dictionary<Column, CellStyle>();
                }
               _cellStyles[col] = style;
                if (Grid != null)
                {
                    Grid.Invalidate(new CellRange(this.Index, col.Index));
                }
            }
        }
        /// <summary>
        /// この行では、セルに適用したスタイルを取得します
        /// </summary>
        public CellStyle GetCellStyle(Column col)
        {
            CellStyle s = null;
            if (_cellStyles != null)
            {
                _cellStyles.TryGetValue(col,out s);
            }
            return s;
        }

    }
}

コードのコピー
Class MainWindow
    Inherits Window
    Public Sub New()
        InitializeComponent()
        Dim products As ListCollectionView = Product.GetProducts(250)
        TryCast(products.GetItemAt(0), Product).Price = -10
        TryCast(products.GetItemAt(1), Product).Price = -10

        C1FlexGrid1.ItemsSource = products

    End Sub

    Private Sub btnExport_Click(sender As Object, e As RoutedEventArgs)
        Dim dlg = New Microsoft.Win32.SaveFileDialog()
        dlg.DefaultExt = "xlsx"
        dlg.Filter = "Excel Workbook (*.xlsx)|*.xlsx|" + "HTML File (*.htm;*.html)|*.htm;*.html|" + "Comma Separated Values (*.csv)|*.csv|" + "Text File (*.txt)|*.txt"
        If dlg.ShowDialog() = True Then
            Dim ext = System.IO.Path.GetExtension(dlg.SafeFileName).ToLower()
            ext = If(ext = ".htm", "ehtm", If(ext = ".html", "ehtm", ext))
            Select Case ext
                Case "ehtm"
                    If True Then
                        C1FlexGrid1.Save(dlg.FileName, C1.WPF.FlexGrid.FileFormat.Html, C1.WPF.FlexGrid.SaveOptions.Formatted)
                        Exit Select
                    End If
                Case ".csv"
                    If True Then
                        C1FlexGrid1.Save(dlg.FileName, C1.WPF.FlexGrid.FileFormat.Csv, C1.WPF.FlexGrid.SaveOptions.Formatted)
                        Exit Select
                    End If
                Case ".txt"
                    If True Then
                        C1FlexGrid1.Save(dlg.FileName, C1.WPF.FlexGrid.FileFormat.Text, C1.WPF.FlexGrid.SaveOptions.Formatted)
                        Exit Select
                    End If
                Case Else
                    If True Then
                        Save(dlg.FileName, C1FlexGrid1)
                        Exit Select
                    End If
            End Select
        End If
    End Sub

    Public Sub Save(filename As String, flexgrid As C1.WPF.FlexGrid.C1FlexGrid)
        ' 保存するBookを作成します
        Dim book = New C1XLBook()
        book.Sheets.Clear()
        Dim xlSheet = book.Sheets.Add("Sheet1")
        ExcelFilter.Save(flexgrid, xlSheet)


        ' Bookを保存します
        book.Save(filename, C1.WPF.Excel.FileFormat.OpenXml)
    End Sub

End Class
コードのコピー
Imports C1.WPF.Excel
Imports C1.WPF.FlexGrid

Friend NotInheritable Class ExcelFilter
    Private Shared _lastBook As C1XLBook
    Private Shared _cellStyles As New Dictionary(Of XLStyle, ExcelCellStyle)()

    Private Shared _excelStyles As New Dictionary(Of ExcelCellStyle, XLStyle)()
    '---------------------------------------------------------------------------------
#Region "** object model"

    ''' <summary>
    ''' C1FlexGridのコンテンツをXLSheetに保存します
    ''' </summary>
    Public Shared Sub Save(flex As C1FlexGrid, sheet As XLSheet)
        ' 新しいbookの場合は、スタイルのキャッシュをクリアします
        If Not Object.ReferenceEquals(sheet.Book, _lastBook) Then
            _cellStyles.Clear()
            _excelStyles.Clear()
            _lastBook = sheet.Book
        End If

        ' グローバルパラメーターを保存します
        sheet.DefaultRowHeight = PixelsToTwips(flex.Rows.DefaultSize)
        sheet.DefaultColumnWidth = PixelsToTwips(flex.Columns.DefaultSize)
        sheet.Locked = flex.IsReadOnly
        sheet.ShowGridLines = flex.GridLinesVisibility <> GridLinesVisibility.None
        sheet.ShowHeaders = flex.HeadersVisibility <> HeadersVisibility.None
        sheet.OutlinesBelow = flex.GroupRowPosition = GroupRowPosition.BelowData

        ' 列を保存します
        sheet.Columns.Clear()
        For Each col As Column In flex.Columns
            Dim c As XLColumn = sheet.Columns.Add()
            If Not col.Width.IsAuto Then
                c.Width = PixelsToTwips(col.ActualWidth)
            End If
            c.Visible = col.Visible
            If TypeOf col.CellStyle Is ExcelCellStyle Then
                c.Style = GetXLStyle(flex, sheet, DirectCast(col.CellStyle, ExcelCellStyle))
            End If
        Next

        sheet.Rows.Clear()

        ' 列ヘッダーを保存します
        Dim headerStyle As XLStyle = Nothing
        headerStyle = New XLStyle(sheet.Book)
        headerStyle.Font = New XLFont("Arial", 10, True, False)

        For Each row As Row In flex.ColumnHeaders.Rows
            Dim r As XLRow = sheet.Rows.Add()
            If row.Height > -1 Then
                r.Height = PixelsToTwips(row.Height)
            End If
            If TypeOf row.CellStyle Is ExcelCellStyle Then
                r.Style = GetXLStyle(flex, sheet, DirectCast(row.CellStyle, ExcelCellStyle))
            End If
            If TypeOf row Is ExcelRow Then
                r.OutlineLevel = DirectCast(row, ExcelRow).Level
            End If
            For c As Integer = 0 To flex.ColumnHeaders.Columns.Count - 1
                ' セル値を保存します
                Dim cell As XLCell = sheet(row.Index, c)
                Dim colHeader As String = If(flex.ColumnHeaders(row.Index, c) IsNot Nothing, flex.ColumnHeaders(row.Index, c).ToString(), flex.Columns(c).ColumnName)
                cell.Value = colHeader

                ' 列ヘッダーを太字にします

                cell.Style = headerStyle
            Next
            r.Visible = row.Visible
        Next



        ' 行を保存します
        For Each row As Row In flex.Rows
            Dim r As XLRow = sheet.Rows.Add()
            If row.Height > -1 Then
                r.Height = PixelsToTwips(row.Height)
            End If
            If TypeOf row.CellStyle Is ExcelCellStyle Then
                r.Style = GetXLStyle(flex, sheet, DirectCast(row.CellStyle, ExcelCellStyle))
            End If
            If TypeOf row Is ExcelRow Then
                r.OutlineLevel = DirectCast(row, ExcelRow).Level
            End If
            r.Visible = row.Visible
        Next

        ' 選択範囲を保存します
        For r As Integer = flex.ColumnHeaders.Rows.Count To flex.Rows.Count - 1
            For c As Integer = 0 To flex.Columns.Count - 1
                ' セル値を保存します
                Dim cell As XLCell = sheet(r, c)
                Dim obj As Object = flex(r, c)
                cell.Value = If(TypeOf obj Is FrameworkElement, 0, obj)

                ' セルの数式とスタイルを保存します
                Dim row As ExcelRow = TryCast(flex.Rows(r), ExcelRow)
                If row IsNot Nothing Then
                    ' セルの数式を保存します
                    Dim col As Column = flex.Columns(c)

                    ' セルのスタイルを保存します
                    Dim cs As ExcelCellStyle = TryCast(row.GetCellStyle(col), ExcelCellStyle)
                    If cs IsNot Nothing Then
                        cell.Style = GetXLStyle(flex, sheet, cs)
                    End If
                End If
            Next
        Next

        ' 選択範囲を保存します
        Dim sel As CellRange = flex.Selection
        If sel.IsValid Then
            Dim xlSel As XLCellRange = New XLCellRange(sheet, sel.Row, sel.Row2, sel.Column, sel.Column2)
            sheet.SelectedCells.Clear()
            sheet.SelectedCells.Add(xlSel)
        End If
    End Sub

#End Region

    '---------------------------------------------------------------------------------
#Region "** implementation"

    Private Shared Function TwipsToPixels(twips As Double) As Double
        Return Convert.ToInt32(twips / 1440.0 * 96.0 * 1.2 + 0.5)
    End Function
    Private Shared Function PixelsToTwips(pixels As Double) As Integer
        Return Convert.ToInt32(pixels * 1440.0 / 96.0 / 1.2 + 0.5)
    End Function
    Private Shared Function PointsToPixels(points As Double) As Double
        Return points / 72.0 * 96.0 * 1.2
    End Function
    Private Shared Function PixelsToPoints(pixels As Double) As Double
        Return pixels * 72.0 / 96.0 / 1.2
    End Function

    ' Excelスタイルをクリッドスタイルに変更します
    Private Shared Function GetCellStyle(x As XLStyle) As ExcelCellStyle
        ' キャッシュを検索します
        Dim s As ExcelCellStyle = Nothing
        If _cellStyles.TryGetValue(x, s) Then
            Return s
        End If

        ' 見つかりません。スタイルを作成します
        s = New ExcelCellStyle()

        ' 配置
        Select Case x.AlignHorz
            Case XLAlignHorzEnum.Left
                s.HorizontalAlignment = HorizontalAlignment.Left
                Exit Select
            Case XLAlignHorzEnum.Center
                s.HorizontalAlignment = HorizontalAlignment.Center
                Exit Select
            Case XLAlignHorzEnum.Right
                s.HorizontalAlignment = HorizontalAlignment.Right
                Exit Select
        End Select
        Select Case x.AlignVert
            Case XLAlignVertEnum.Top
                s.VerticalAlignment = VerticalAlignment.Top
                Exit Select
            Case XLAlignVertEnum.Center
                s.VerticalAlignment = VerticalAlignment.Center
                Exit Select
            Case XLAlignVertEnum.Bottom
                s.VerticalAlignment = VerticalAlignment.Bottom
                Exit Select
        End Select
        s.TextWrapping = x.WordWrap

        ' カラー
        If x.BackPattern = XLPatternEnum.Solid AndAlso IsColorValid(x.BackColor) Then
            s.Background = New SolidColorBrush(x.BackColor)
        End If
        If IsColorValid(x.ForeColor) Then
            s.Foreground = New SolidColorBrush(x.ForeColor)
        End If

        ' フォント
        Dim font As XLFont = x.Font
        If font IsNot Nothing Then
            s.FontFamily = New FontFamily(font.FontName)
            s.FontSize = PointsToPixels(font.FontSize)
            If font.Bold Then
                s.FontWeight = FontWeights.Bold
            End If
            If font.Italic Then
                s.FontStyle = FontStyles.Italic
            End If
            If font.Underline <> XLUnderlineStyle.None Then
                s.TextDecorations = TextDecorations.Underline
            End If
        End If

        ' 書式
        If Not String.IsNullOrEmpty(x.Format) Then
            s.Format = XLStyle.FormatXLToDotNet(x.Format)
        End If

        ' 境界線
        s.CellBorderThickness = New Thickness(GetBorderThickness(x.BorderLeft), GetBorderThickness(x.BorderTop), GetBorderThickness(x.BorderRight), GetBorderThickness(x.BorderBottom))
        s.CellBorderBrushLeft = GetBorderBrush(x.BorderColorLeft)
        s.CellBorderBrushTop = GetBorderBrush(x.BorderColorTop)
        s.CellBorderBrushRight = GetBorderBrush(x.BorderColorRight)
        s.CellBorderBrushBottom = GetBorderBrush(x.BorderColorBottom)

        ' キャッシュに保存して戻します
        _cellStyles(x) = s
        Return s
    End Function

    ' グリッドスタイルをExcelスタイルに変更します
    Private Shared Function GetXLStyle(flex As C1FlexGrid, sheet As XLSheet, s As ExcelCellStyle) As XLStyle
        ' キャッシュで検索します
        Dim x As XLStyle = Nothing
        If _excelStyles.TryGetValue(s, x) Then
            Return x
        End If

        ' 見つかりません。スタイルを作成します
        x = New XLStyle(sheet.Book)

        ' 配置
        If s.HorizontalAlignment.HasValue Then
            Select Case s.HorizontalAlignment.Value
                Case HorizontalAlignment.Left
                    x.AlignHorz = XLAlignHorzEnum.Left
                    Exit Select
                Case HorizontalAlignment.Center
                    x.AlignHorz = XLAlignHorzEnum.Center
                    Exit Select
                Case HorizontalAlignment.Right
                    x.AlignHorz = XLAlignHorzEnum.Right
                    Exit Select
            End Select
        End If
        If s.VerticalAlignment.HasValue Then
            Select Case s.VerticalAlignment.Value
                Case VerticalAlignment.Top
                    x.AlignVert = XLAlignVertEnum.Top
                    Exit Select
                Case VerticalAlignment.Center
                    x.AlignVert = XLAlignVertEnum.Center
                    Exit Select
                Case VerticalAlignment.Bottom
                    x.AlignVert = XLAlignVertEnum.Bottom
                    Exit Select
            End Select
        End If
        If s.TextWrapping.HasValue Then
            x.WordWrap = s.TextWrapping.Value
        End If

        ' カラー
        If TypeOf s.Background Is SolidColorBrush Then
            x.BackColor = DirectCast(s.Background, SolidColorBrush).Color
            x.BackPattern = XLPatternEnum.Solid
        End If
        If TypeOf s.Foreground Is SolidColorBrush Then
            x.ForeColor = DirectCast(s.Foreground, SolidColorBrush).Color
        End If

        ' フォント
        Dim fontName As String = flex.FontFamily.Source
        Dim fontSize As Double = flex.FontSize
        Dim bold As Boolean = False
        Dim italic As Boolean = False
        Dim underline As Boolean = False
        Dim hasFont As Boolean = False
        If s.FontFamily IsNot Nothing Then
            fontName = s.FontFamily.Source
            hasFont = True
        End If
        If s.FontSize.HasValue Then
            fontSize = s.FontSize.Value
            hasFont = True
        End If
        If s.FontWeight.HasValue Then
            bold = s.FontWeight.Value = FontWeights.Bold OrElse s.FontWeight.Value = FontWeights.ExtraBold OrElse s.FontWeight.Value = FontWeights.SemiBold
            hasFont = True
        End If
        If s.FontStyle.HasValue Then
            italic = s.FontStyle.Value = FontStyles.Italic
            hasFont = True
        End If
        If s.TextDecorations IsNot Nothing Then
            underline = True
            hasFont = True
        End If
        If hasFont Then
            fontSize = PixelsToPoints(fontSize)
            If underline Then
                Dim color As Color = Colors.Black
                If TypeOf flex.Foreground Is SolidColorBrush Then
                    color = DirectCast(flex.Foreground, SolidColorBrush).Color
                End If
                If TypeOf s.Foreground Is SolidColorBrush Then
                    color = DirectCast(s.Foreground, SolidColorBrush).Color
                End If
                x.Font = New XLFont(fontName, Convert.ToSingle(fontSize), bold, italic, False, XLFontScript.None, _
                    XLUnderlineStyle.[Single], color)
            Else
                x.Font = New XLFont(fontName, Convert.ToSingle(fontSize), bold, italic)
            End If
        End If

        ' 書式
        If Not String.IsNullOrEmpty(s.Format) Then
            x.Format = XLStyle.FormatDotNetToXL(s.Format)
        End If

        ' 境界線
        If s.CellBorderThickness.Left > 0 AndAlso TypeOf s.CellBorderBrushLeft Is SolidColorBrush Then
            x.BorderLeft = GetBorderLineStyle(s.CellBorderThickness.Left)
            x.BorderColorLeft = DirectCast(s.CellBorderBrushLeft, SolidColorBrush).Color
        End If
        If s.CellBorderThickness.Top > 0 AndAlso TypeOf s.CellBorderBrushTop Is SolidColorBrush Then
            x.BorderTop = GetBorderLineStyle(s.CellBorderThickness.Top)
            x.BorderColorTop = DirectCast(s.CellBorderBrushTop, SolidColorBrush).Color
        End If
        If s.CellBorderThickness.Right > 0 AndAlso TypeOf s.CellBorderBrushRight Is SolidColorBrush Then
            x.BorderRight = GetBorderLineStyle(s.CellBorderThickness.Right)
            x.BorderColorRight = DirectCast(s.CellBorderBrushRight, SolidColorBrush).Color
        End If
        If s.CellBorderThickness.Bottom > 0 AndAlso TypeOf s.CellBorderBrushBottom Is SolidColorBrush Then
            x.BorderBottom = GetBorderLineStyle(s.CellBorderThickness.Bottom)
            x.BorderColorBottom = DirectCast(s.CellBorderBrushBottom, SolidColorBrush).Color
        End If

        ' キャッシュに保存して戻します
        _excelStyles(s) = x
        Return x
    End Function
    Private Shared Function GetBorderThickness(ls As XLLineStyleEnum) As Double
        Select Case ls
            Case XLLineStyleEnum.None
                Return 0
            Case XLLineStyleEnum.Hair
                Return 0.5
            Case XLLineStyleEnum.Thin, XLLineStyleEnum.ThinDashDotDotted, XLLineStyleEnum.ThinDashDotted, XLLineStyleEnum.Dashed, XLLineStyleEnum.Dotted
                Return 1
            Case XLLineStyleEnum.Medium, XLLineStyleEnum.MediumDashDotDotted, XLLineStyleEnum.MediumDashDotted, XLLineStyleEnum.MediumDashed, XLLineStyleEnum.SlantedMediumDashDotted
                Return 2
            Case XLLineStyleEnum.[Double], XLLineStyleEnum.Thick
                Return 3
        End Select
        Return 0
    End Function
    Private Shared Function GetBorderLineStyle(t As Double) As XLLineStyleEnum
        If t = 0 Then
            Return XLLineStyleEnum.None
        End If
        If t < 1 Then
            Return XLLineStyleEnum.Hair
        End If
        If t < 2 Then
            Return XLLineStyleEnum.Thin
        End If
        If t < 3 Then
            Return XLLineStyleEnum.Medium
        End If
        Return XLLineStyleEnum.Thick
    End Function
    Private Shared Function GetBorderBrush(color As Color) As Brush
        Return If(IsColorValid(color), New SolidColorBrush(color), Nothing)
    End Function
    Private Shared Function IsColorValid(color As Color) As Boolean
        Return color.A > 0
        ' == 0xff;
    End Function

#End Region
End Class
コードのコピー
Imports C1.WPF.FlexGrid
Imports System.ComponentModel

Public Class ExcelCellStyle
    Inherits CellStyle
    ' ** フィールド
    Private _format As String
    Private _bdrThickness As Thickness
    Private _bdrLeft As Brush
    Private _bdrTop As Brush
    Private _bdrRight As Brush
    Private _bdrBottom As Brush

    Private Shared _thicknessEmpty As New Thickness(0)
    ' ** オブジェクト・モデル
    Public Property Format() As String
        Get
            Return _format
        End Get
        Set(value As String)
            If value <> _format Then
                _format = value
                OnPropertyChanged(New PropertyChangedEventArgs("Format"))
            End If
        End Set
    End Property
    Public Property CellBorderThickness() As Thickness
        Get
            Return _bdrThickness
        End Get
        Set(value As Thickness)
            If value <> _bdrThickness Then
                _bdrThickness = value
                OnPropertyChanged(New PropertyChangedEventArgs("BorderThickness"))
            End If
        End Set
    End Property
    Public Property CellBorderBrushLeft() As Brush
        Get
            Return _bdrLeft
        End Get
        Set(value As Brush)
            If Not Object.ReferenceEquals(value, _bdrLeft) Then
                _bdrLeft = value
                OnPropertyChanged(New PropertyChangedEventArgs("BorderColorLeft"))
            End If
        End Set
    End Property
    Public Property CellBorderBrushTop() As Brush
        Get
            Return _bdrTop
        End Get
        Set(value As Brush)
            If Not Object.ReferenceEquals(value, _bdrTop) Then
                _bdrTop = value
                OnPropertyChanged(New PropertyChangedEventArgs("BorderColorTop"))
            End If
        End Set
    End Property
    Public Property CellBorderBrushRight() As Brush
        Get
            Return _bdrRight
        End Get
        Set(value As Brush)
            If Not Object.ReferenceEquals(value, _bdrRight) Then
                _bdrRight = value
                OnPropertyChanged(New PropertyChangedEventArgs("BorderColorRight"))
            End If
        End Set
    End Property
    Public Property CellBorderBrushBottom() As Brush
        Get
            Return _bdrBottom
        End Get
        Set(value As Brush)
            If Not Object.ReferenceEquals(value, _bdrBottom) Then
                _bdrBottom = value
                OnPropertyChanged(New PropertyChangedEventArgs("BorderColorBottom"))
            End If
        End Set
    End Property

    ' ** オーバーライド
    Public Overrides Sub Apply(bdr As Border, selState As SelectedState)
        MyBase.Apply(bdr, selState)
        ApplyBorder(bdr, _bdrLeft, New Thickness(_bdrThickness.Left, 0, 0, 0))
        ApplyBorder(bdr, _bdrTop, New Thickness(0, _bdrThickness.Top, 0, 0))
        ApplyBorder(bdr, _bdrRight, New Thickness(0, 0, _bdrThickness.Right, 0))
        ApplyBorder(bdr, _bdrBottom, New Thickness(0, 0, 0, _bdrThickness.Bottom))
    End Sub
    Private Sub ApplyBorder(bdr As Border, br As Brush, t As Thickness)
        If br IsNot Nothing AndAlso t <> _thicknessEmpty Then
            ' 内部の境界線を作成します
            Dim inner As Border = New Border()
            inner.BorderThickness = t
            inner.BorderBrush = br

            ' コンテンツに拡張します
            Dim content As Border = bdr.Child
            bdr.Child = inner
            inner.Child = content

            ' パディングします
            inner.Padding = bdr.Padding
            bdr.Padding = _thicknessEmpty
        End If
    End Sub
End Class
コードのコピー
Imports C1.WPF.FlexGrid
Imports System.Globalization

Public Class ExcelRow
    Inherits GroupRow
    ' ** フィールド

    Private _cellStyles As Dictionary(Of Column, CellStyle)
    ' 既定の有効桁数を6桁に設定します
    Private Const DEFAULT_FORMAT As String = "#,##0.######"

    ' ** ctor
    Public Sub New(styleRow As ExcelRow)
        IsReadOnly = False
        If styleRow IsNot Nothing AndAlso styleRow.Grid IsNot Nothing Then
            For Each c As Column In styleRow.Grid.Columns
                Dim cs As CellStyle = styleRow.GetCellStyle(c)
                If cs IsNot Nothing Then
                    Me.SetCellStyle(c, cs.Clone())
                End If
            Next
        End If
    End Sub
    Public Sub New()
        Me.New(Nothing)
    End Sub

    ' ** オブジェクト・モデル

    ''' <summary>
    ''' データを取得する場合、書式を適用するためにオーバーライドされる
    ''' </summary>
    Public Overrides Function GetDataFormatted(col As Column) As String
        ' データを取得します
        Dim data As Object = GetDataRaw(col)

        ' 書式を適用します
        Dim ifmt As IFormattable = TryCast(data, IFormattable)
        If ifmt IsNot Nothing Then
            ' セルの書式を取得します
            Dim s As ExcelCellStyle = TryCast(GetCellStyle(col), ExcelCellStyle)
            Dim fmt As String = If(s IsNot Nothing AndAlso (Not String.IsNullOrEmpty(s.Format)), s.Format, DEFAULT_FORMAT)
            data = ifmt.ToString(fmt, CultureInfo.CurrentUICulture)
        End If

        ' 完了
        Return If(data IsNot Nothing, data.ToString(), String.Empty)
    End Function

    ' ** オブジェクト・モデル

    ''' <summary>
    ''' この行では、セルにスタイルを適用します
    ''' </summary>
    Public Sub SetCellStyle(col As Column, style As CellStyle)
        If Not Object.ReferenceEquals(style, GetCellStyle(col)) Then
            If _cellStyles Is Nothing Then
                _cellStyles = New Dictionary(Of Column, CellStyle)()
            End If
            _cellStyles(col) = style
            If Grid IsNot Nothing Then
                Grid.Invalidate(New CellRange(Me.Index, col.Index))
            End If
        End If
    End Sub
    ''' <summary>
    ''' この行では、セルに適用したスタイルを取得します
    ''' </summary>
    Public Function GetCellStyle(col As Column) As CellStyle
        Dim s As CellStyle = Nothing
        If _cellStyles IsNot Nothing Then
            _cellStyles.TryGetValue(col, s)
        End If
        Return s
    End Function

End Class