/// <summary> /// Преобразует матрицу в текст /// </summary> /// <param name="matrix">Матрица для преобразования</param> /// <returns>Текстовое представление</returns> public static string MatrixToPlainText(MatrixGrid.IMatrix matrix) { if (matrix == null || matrix.Cells == null) { return(string.Empty); } int matrixHeight = (int)matrix.Size.Height, matrixWidth = (int)matrix.Size.Width; string[,] data = new string[matrixHeight, matrixWidth]; // заполнение всего пространства, которое занимает ячейка, кроме верхнего левого угла, символом табуляции Action <MatrixGrid.IMatrixCell> fillSpanningCells = (cell) => { for (int rowIndex = cell.GridRow + 1; rowIndex < cell.GridRow + cell.GridRowSpan; rowIndex++) { for (int columnIndex = cell.GridColumn + 1; columnIndex < cell.GridColumn + cell.GridColumnSpan; columnIndex++) { data[rowIndex, columnIndex] = "\t"; } } }; for (int rowIndex = 0; rowIndex < matrixHeight; rowIndex++) { for (int columnIndex = 0; columnIndex < matrixWidth; columnIndex++) { MatrixGrid.IMatrixCell cell = matrix.Cells[rowIndex, columnIndex]; if (cell == null) { continue; } data[rowIndex, columnIndex] = GetMatrixCellValueAsString(cell); if (columnIndex < matrixWidth - 1) { data[rowIndex, columnIndex] += "\t"; } fillSpanningCells(cell); } } StringBuilder sb = new StringBuilder(); for (int rowIndex = 0; rowIndex < matrixHeight; rowIndex++) { for (int columnIndex = 0; columnIndex < matrixWidth; columnIndex++) { sb.Append(data[rowIndex, columnIndex]); } sb.AppendLine(); } return(sb.ToString()); }
/// <summary> /// Преобразование матрицы в различные форматы и отправка их в буфер обмена /// </summary> /// <param name="matrix">Матрица</param> public static void MatrixToClipboard(MatrixGrid.IMatrix matrix) { IDataObject dataObject = new DataObject(); ((IDataObject)dataObject).SetData(DataFormats.Html, CreateHtmlDataFormatFromMatrix(matrix)); ((IDataObject)dataObject).SetData(DataFormats.UnicodeText, MatrixToPlainText(matrix)); string xaml = FrameworkContentElementToXaml(MatrixToFlowDocumentSectionWithTable(matrix)); ((IDataObject)dataObject).SetData(DataFormats.Rtf, XamlToRtf(xaml)); ((IDataObject)dataObject).SetData(DataFormats.Xaml, xaml); Clipboard.SetDataObject(dataObject, true); }
private static string CreateHtmlDataFormatFromMatrix(MatrixGrid.IMatrix matrix, string style = null) { // Структура Html заголовка // Version:1.0 // StartHTML:000000000 // EndHTML:000000000 // StartFragment:000000000 // EndFragment:000000000 // StartSelection:000000000 // EndSelection:000000000 const string HtmlHeader = "Version:1.0\r\nStartHTML:{0:D10}\r\nEndHTML:{1:D10}\r\nStartFragment:{2:D10}\r\nEndFragment:{3:D10}\r\n"; const string HtmlStartFragmentComment = @"<!--StartFragment-->"; const string HtmlEndFragmentComment = @"<!--EndFragment-->"; // каждое из шести чисел заголовка представлено как "{0:D10}" в строке формата // т.е. число представляется 10-ю разрядами ("0123456789") int startHTML = HtmlHeader.Length + (4 * ("0123456789".Length - "{0:D10}".Length)); StringBuilder sbHtml = new StringBuilder(); sbHtml.AppendLine(@"<html xmlns:o=""urn:schemas-microsoft-com:office:office"" xmlns:x=""urn:schemas-microsoft-com:office:excel"" xmlns=""http://www.w3.org/TR/REC-html40"">"); sbHtml.AppendLine("<head>"); sbHtml.AppendLine(@"<meta http-equiv=Content-Type content=""text/html; charset=utf-8"" >"); sbHtml.AppendLine("<title></title>"); sbHtml.AppendFormat("<style type=\"text/css\">\r\n{0}\r\n</style>\r\n", style ?? @"table {mso-displayed-decimal-separator:""\,"";mso-displayed-thousand-separator:"" ""; width:100%;} br {mso-data-placement:same-cell;} th {font-size:11.0pt; font-family:Calibri, sans-serif; border: 1.0pt solid windowtext; mso-protection:locked visible;} td {font-size:11.0pt; font-family:Calibri, sans-serif; border: 0.5pt solid windowtext; mso-number-format:General; mso-protection:locked visible; }"); sbHtml.AppendLine("</head>"); sbHtml.AppendLine("<body>"); sbHtml.AppendLine(HtmlStartFragmentComment); int fragmentStart = startHTML + GetByteCount(sbHtml); string htmlTable = MatrixToHtmlTable(matrix) ?? string.Empty; // re-encode the string so it will work correctly (fixed in CLR 4.0) if (Environment.Version.Major < 4 && htmlTable.Length != Encoding.UTF8.GetByteCount(htmlTable)) { htmlTable = Encoding.Default.GetString(Encoding.UTF8.GetBytes(htmlTable)); } sbHtml.AppendLine(htmlTable); int fragmentEnd = startHTML + GetByteCount(sbHtml); sbHtml.AppendLine(HtmlEndFragmentComment); sbHtml.Append("\r\n</body>\r\n</html>"); int endHTML = startHTML + GetByteCount(sbHtml); sbHtml.Insert(0, string.Format(HtmlHeader, startHTML, endHTML, fragmentStart, fragmentEnd)); string result = sbHtml.ToString(); byte[] bytes = System.Text.Encoding.UTF8.GetBytes(result); // result = System.Text.Encoding.UTF8.GetString(bytes); var b = bytes.Length == System.Text.Encoding.UTF8.GetByteCount(result); return(result); }
/// <summary> /// Преобразует матрицу во System.Windows.Documents.Section, содержащий Table /// </summary> /// <param name="matrix">Матрица для преобразования</param> /// <returns>System.Windows.Documents.Section</returns> public static System.Windows.Documents.Section MatrixToFlowDocumentSectionWithTable(MatrixGrid.IMatrix matrix) { if (matrix == null || matrix.Cells == null) { return(new System.Windows.Documents.Section()); } int matrixHeight = (int)matrix.Size.Height, matrixWidth = (int)matrix.Size.Width; int matrixColumnHeadersHeight = matrix.Cells[0, 0].GridRowSpan; int matrixRowsHeadersWidth = matrix.Cells[0, 0].GridColumnSpan; Action <MatrixGrid.IMatrixCell, System.Windows.Documents.TableCell> setBorders = (matrixCell, tableCell) => { Thickness thickness = (Thickness)Converters.HeaderBorderThicknessConverter.Singleton.Convert(matrixCell, null); tableCell.BorderThickness = thickness; }; System.Windows.Documents.Table table = new System.Windows.Documents.Table(); #region resources ResourceDictionary rd = new ResourceDictionary(); rd.Source = new Uri("/ui.controls.wpf.reporting;component/Themes/FlowDocumentTableStyles.xaml", UriKind.RelativeOrAbsolute); table.Resources = rd; #endregion // добавление колонок // for (int columnIndex = 0; columnIndex < matrixWidth; columnIndex++) // table.Columns.Add(new System.Windows.Documents.TableColumn()); #region шапка таблицы System.Windows.Documents.TableRowGroup headerRowGroup = new System.Windows.Documents.TableRowGroup(); for (int rowIndex = 0; rowIndex < matrixColumnHeadersHeight; rowIndex++) { System.Windows.Documents.TableRow row = new System.Windows.Documents.TableRow(); for (int columnIndex = 0; columnIndex < matrixWidth; columnIndex++) { MatrixGrid.IMatrixCell cell = matrix.Cells[rowIndex, columnIndex]; if (cell == null) { continue; } System.Windows.Documents.TableCell tableCell = new System.Windows.Documents.TableCell(); setBorders(cell, tableCell); if (cell is MatrixGrid.IMatrixHeader headerCell) { if (headerCell.CellType != MatrixGrid.MatrixCellType.Empty) { tableCell.Background = System.Windows.Media.Brushes.LightGray; } else { if (headerCell.CellType == MatrixGrid.MatrixCellType.ColumnsGroupHeader || headerCell.CellType == MatrixGrid.MatrixCellType.ColumnSummaryHeader) { tableCell.Background = System.Windows.Media.Brushes.DarkGray; tableCell.FontWeight = FontWeights.SemiBold; } } } tableCell.RowSpan = cell.GridRowSpan; tableCell.ColumnSpan = cell.GridColumnSpan; tableCell.Blocks.Add(new System.Windows.Documents.Paragraph(new System.Windows.Documents.Run(GetMatrixCellValueAsString(cell)))); row.Cells.Add(tableCell); } headerRowGroup.Rows.Add(row); } table.RowGroups.Add(headerRowGroup); #endregion #region данные int dataRowsMaxGridRow = matrix.ShowColumnsTotal ? matrixHeight - 1 : matrixHeight; System.Windows.Documents.TableRowGroup dataRowGroup = new System.Windows.Documents.TableRowGroup(); for (int rowIndex = matrixColumnHeadersHeight; rowIndex < dataRowsMaxGridRow; rowIndex++) { System.Windows.Documents.TableRow row = new System.Windows.Documents.TableRow(); for (int columnIndex = 0; columnIndex < matrixWidth; columnIndex++) { MatrixGrid.IMatrixCell cell = matrix.Cells[rowIndex, columnIndex]; if (cell == null) { continue; } System.Windows.Documents.TableCell tableCell = new System.Windows.Documents.TableCell(); setBorders(cell, tableCell); if (cell is MatrixGrid.IMatrixHeader headerCell) { tableCell.Background = System.Windows.Media.Brushes.LightGray; } else { if (cell is MatrixGrid.IMatrixSummaryCell summaryCell) { if (summaryCell.SummaryType == MatrixGrid.MatrixSummaryType.RowSummary || summaryCell.SummaryType == MatrixGrid.MatrixSummaryType.RowsGroupSummary) { tableCell.Background = System.Windows.Media.Brushes.DarkGray; tableCell.FontWeight = FontWeights.SemiBold; } } } tableCell.RowSpan = cell.GridRowSpan; tableCell.ColumnSpan = cell.GridColumnSpan; tableCell.Blocks.Add(new System.Windows.Documents.Paragraph(new System.Windows.Documents.Run(GetMatrixCellValueAsString(cell)))); row.Cells.Add(tableCell); } dataRowGroup.Rows.Add(row); } table.RowGroups.Add(dataRowGroup); #endregion #region строка итогов if (matrix.ShowColumnsTotal) { System.Windows.Documents.TableRowGroup totalRowGroup = new System.Windows.Documents.TableRowGroup(); System.Windows.Documents.TableRow row = new System.Windows.Documents.TableRow(); for (int columnIndex = 0; columnIndex < matrixWidth; columnIndex++) { MatrixGrid.IMatrixCell cell = matrix.Cells[matrixHeight - 1, columnIndex]; if (cell == null) { continue; } System.Windows.Documents.TableCell tableCell = new System.Windows.Documents.TableCell(); setBorders(cell, tableCell); tableCell.Background = System.Windows.Media.Brushes.DarkGray; tableCell.FontWeight = FontWeights.Bold; if (cell is MatrixGrid.IMatrixSummaryCell summaryCell) { if (summaryCell.CellType == MatrixGrid.MatrixCellType.RowSummaryHeader) { tableCell.FontWeight = FontWeights.SemiBold; } else if (summaryCell.SummaryType == MatrixGrid.MatrixSummaryType.TotalSummary) { tableCell.Background = System.Windows.Media.Brushes.Gray; tableCell.Foreground = System.Windows.Media.Brushes.White; tableCell.FontWeight = FontWeights.ExtraBold; } } else { tableCell.Background = System.Windows.Media.Brushes.LightGray; } tableCell.RowSpan = cell.GridRowSpan; tableCell.ColumnSpan = cell.GridColumnSpan; tableCell.Blocks.Add(new System.Windows.Documents.Paragraph(new System.Windows.Documents.Run(GetMatrixCellValueAsString(cell)))); row.Cells.Add(tableCell); } totalRowGroup.Rows.Add(row); table.RowGroups.Add(totalRowGroup); } #endregion System.Windows.Documents.Section section = new System.Windows.Documents.Section(); section.Blocks.Add(new System.Windows.Documents.Paragraph(new System.Windows.Documents.Run(matrix.Header) { FontWeight = FontWeights.Bold }) { TextAlignment = TextAlignment.Center }); section.Blocks.Add(table); section.Blocks.Add(new System.Windows.Documents.Paragraph(new System.Windows.Documents.Run(matrix.Description) { FontWeight = FontWeights.Thin, FontStyle = FontStyles.Italic }) { TextAlignment = TextAlignment.Left }); return(section); }
/// <summary> /// Преобразует матрицу в HTML таблицу /// </summary> /// <param name="matrix">Матрица для преобразования</param> /// <returns>HTML таблица</returns> public static string MatrixToHtmlTable(MatrixGrid.IMatrix matrix) { Func <MatrixGrid.IMatrixCell, HtmlTableCell.ThScope> setCellScope = (matrixCell) => { if (matrixCell is MatrixGrid.IMatrixHeader headerCell) { if (headerCell.CellType == MatrixGrid.MatrixCellType.ColumnHeader || headerCell.CellType == MatrixGrid.MatrixCellType.ColumnsGroupHeader || headerCell.CellType == MatrixGrid.MatrixCellType.ColumnSummaryHeader) { if (headerCell.ChildrenCount > 0) { return(HtmlTableCell.ThScope.colgroup); } else { return(HtmlTableCell.ThScope.col); } } else { if (headerCell.CellType == MatrixGrid.MatrixCellType.RowHeader || headerCell.CellType == MatrixGrid.MatrixCellType.RowsGroupHeader || headerCell.CellType == MatrixGrid.MatrixCellType.RowSummaryHeader) { if (headerCell.ChildrenCount > 0) { return(HtmlTableCell.ThScope.rowgroup); } else { return(HtmlTableCell.ThScope.row); } } else { return(HtmlTableCell.ThScope.none); } } } else { return(HtmlTableCell.ThScope.none); } }; Func <MatrixGrid.IMatrixCell, HtmlTableCell> matrixCellToHtmlCell = (matrixCell) => new HtmlTableCell() { Value = GetMatrixCellValueAsString(matrixCell), RowSpan = matrixCell.GridRowSpan, ColSpan = matrixCell.GridColumnSpan, Scope = setCellScope(matrixCell), }; Func <MatrixGrid.IMatrixCell, string> getMatrixCellStyleForHtml = (matrixCell) => { Thickness thickness = (Thickness)Converters.HeaderBorderThicknessConverter.Singleton.Convert(matrixCell, null); string borderColor = "gray"; return(string.Format("border-top: {1}pt solid {0}; border-bottom: {2}pt solid {0}; border-left: {3}pt solid {0}; border-right: {4}pt solid {0}; {5};", borderColor, (thickness.Top / 2).ToString("N1", System.Globalization.CultureInfo.InvariantCulture), (thickness.Bottom / 2).ToString("N1", System.Globalization.CultureInfo.InvariantCulture), (thickness.Left / 2).ToString("N1", System.Globalization.CultureInfo.InvariantCulture), (thickness.Right / 2).ToString("N1", System.Globalization.CultureInfo.InvariantCulture), matrixCell is MatrixGrid.IMatrixSummaryCell summaryCell ? (summaryCell.SummaryType == MatrixGrid.MatrixSummaryType.TotalSummary ? "font-weight: bolder; background-color: Gray; color: White" : "font-weight: bold; background-color: LightGray") : (matrixCell is MatrixGrid.IMatrixHeader headerCell ? (headerCell.CellType is MatrixGrid.MatrixCellType.RowHeader or MatrixGrid.MatrixCellType.RowsGroupHeader or MatrixGrid.MatrixCellType.RowSummaryHeader ? "font-weight: bold" : string.Empty) : string.Empty))); }; StringBuilder sb = new StringBuilder(); sb.AppendLine("<TABLE CELLSPACING=0 border=0 style='border-collapse: collapse;'>"); // пустая ячейка в верхнем левом углу должна быть одна // и за ней ожидается строка(и) заголовков столбцов var emptyCell = matrix.Items.Cast <MatrixGrid.IMatrixHeader>().Where(i => i.CellType == MatrixGrid.MatrixCellType.Empty).FirstOrDefault(); if (emptyCell != null) { sb.AppendLine("<THEAD>"); FormatHelper.HtmlFormatTableCell(matrixCellToHtmlCell(emptyCell), true, false, sb, cellTag: "TH", cellStyle: getMatrixCellStyleForHtml(emptyCell)); // список строк матрицы, упорядоченный по номеру строки var rowsWithColumnHeaders = matrix.Items .Where(i => i.CellType == MatrixGrid.MatrixCellType.ColumnHeader || i.CellType == MatrixGrid.MatrixCellType.ColumnsGroupHeader || i.CellType == MatrixGrid.MatrixCellType.ColumnSummaryHeader) .Where(i => i.GridRow < emptyCell.GridRowSpan) .GroupBy(i => i.GridRow) .OrderBy(i => i.Key) .ToList(); bool flag = false; foreach (var row in rowsWithColumnHeaders) { // список столбцов матрицы, упорядоченный по номеру столбца var columns = row .GroupBy(i => i.GridColumn) .OrderBy(i => i.Key); int columnsCount = columns.Count(); int index = 0; foreach (var column in columns) { MatrixGrid.IMatrixCell cell = column.FirstOrDefault(); FormatHelper.HtmlFormatTableCell(matrixCellToHtmlCell(cell), index == 0 && flag, index == columnsCount - 1, sb, cellTag: "TH", cellStyle: getMatrixCellStyleForHtml(cell)); index++; } if (flag == false) { flag = true; } } sb.AppendLine("</THEAD>"); } sb.AppendLine("<TBODY>"); var rowsWithRowHeadersAndDataCells = matrix.Items .Where(i => i.CellType == MatrixGrid.MatrixCellType.RowHeader || i.CellType == MatrixGrid.MatrixCellType.RowsGroupHeader || i.CellType == MatrixGrid.MatrixCellType.DataCell || i.CellType == MatrixGrid.MatrixCellType.RowSummaryHeader || i.CellType == MatrixGrid.MatrixCellType.SummaryCell) .Where(i => i.GridRow >= emptyCell.GridRowSpan) .GroupBy(i => i.GridRow) .OrderBy(i => i.Key) .ToList(); foreach (var row in rowsWithRowHeadersAndDataCells) { // список столбцов матрицы, упорядоченный по номеру столбца var columns = row .GroupBy(i => i.GridColumn) .OrderBy(i => i.Key); int columnsCount = columns.Count(); int index = 0; foreach (var column in columns) { MatrixGrid.IMatrixCell cell = column.FirstOrDefault(); FormatHelper.HtmlFormatTableCell(matrixCellToHtmlCell(cell), index == 0, index == columnsCount - 1, sb, cellStyle: getMatrixCellStyleForHtml(cell)); index++; } } sb.AppendLine("</TBODY>"); sb.Append("</TABLE>"); return(sb.ToString().Replace("\r", string.Empty).Replace("\n", Environment.NewLine).Replace("\r\n", Environment.NewLine)); }