| 基本操作 > エクスポート > 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
|
|