基本操作 > エクスポート > Excelファイルを保存する |
C1FlexGrid の内容は、デフォルトで CSV、HTML形式またはプレーンテキストとしてエクスポートできますが、C1Excel を使用してグリッドのデータをExcel 形式にエクスポートすることも可能です。また、C1Excel ライブラリを使用してエクセル(XLSX形式)にもエクスポートできます。
次の例では、通常の連結グリッド C1FlexGrid に対して ExcelFilter のヘルパークラスを使用してグリッドの内容を XLSX 形式ファイルにエクスポートする方法を示します。基本的に、これらのヘルパークラスをプロジェクトに追加してクラスのメソッドを使用することでデータをエクセルファイルにエクスポートできます。
サンプルコードは次のようになります。
コードのコピー
|
|
---|---|
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 |