трешш

This commit is contained in:
Вера 2024-10-21 18:36:20 +04:00
parent 2df69448b4
commit 92d31a0f49
9 changed files with 214 additions and 304 deletions

View File

@ -57,8 +57,8 @@
customSelectedCheckedListBoxProperty = new MyCustomComponents.CustomSelectedCheckedListBoxProperty();
tabControl = new TabControl();
wordWithImages = new MyCustomComponents.WordWithImages(components);
wordWithTable = new MyCustomComponents.WordWithTable(components);
wordWithDiagram = new MyCustomComponents.WordWithDiagram(components);
wordWithTable = new CustomComponents.NonViewComponents.WordWithTable(components);
Docs.SuspendLayout();
Visual.SuspendLayout();
groupBoxData.SuspendLayout();
@ -411,7 +411,7 @@
private Button buttonWordWithTable;
private Button buttonWordWithImage;
private MyCustomComponents.WordWithImages wordWithImages;
private MyCustomComponents.WordWithTable wordWithTable;
private MyCustomComponents.WordWithDiagram wordWithDiagram;
private CustomComponents.NonViewComponents.WordWithTable wordWithTable;
}
}

View File

@ -1,4 +1,5 @@
using DocumentFormat.OpenXml.Drawing.Charts;
using DocumentFormat.OpenXml.Office2010.Excel;
using MyCustomComponents;
using MyCustomComponents.Models;
using System;
@ -157,30 +158,16 @@ namespace DesktopWithMyVisualComponents
private void buttonWordWithTable_Click(object sender, EventArgs e)
{
wordWithTable.CreateDoc(new WordWithTableDataConfig<Part>
var head = new List<(string, string, string)>
{
FilePath = "C:\\Users\\Вера\\Desktop\\WordWithTableDocx.docx",
Header = "Таблица:",
UseUnion = true,
ColumnsRowsWidth = new List<(int, int)> { (0, 5), (0, 5), (0, 10), (0, 10), (0, 7), (0, 7), (0, 10), (0, 10), (0, 8) },
ColumnUnion = new List<(int StartIndex, int Count)> { (2, 3), (5, 3) },
Headers = new List<(int ColumnIndex, int RowIndex, string Header, string PropertyName)>
{
(0, 0, "Номер", "Id"),
(1, 0, "Парт номер", "Number"),
(2, 0, "Данные о заказе", ""),
(2, 1, "Цена", "Price"),
(3, 1, "Тип комплектующего", "PartType"),
(4, 1, "Модель комплектующего", "Model"),
(5, 0, "Общие данные", ""),
(5, 1, "Энергопотребление", "PowerCons"),
(6, 1, "Наличие гарантии", "Warr"),
(7, 1, "Статус", "State"),
(8, 0, "Заказ", "Order"),
("Данные о заказе", "Цена", "Price"),
("Данные о заказе", "Тип комплектующего", "PartType"),
("Заказ", "", "Order"),
};
},
Data = parts
});
wordWithTable.AddTable<Part>("C:\\Users\\Вера\\Desktop\\WordWithTableDocx.docx", "таблица", head, null, parts);
MessageBox.Show("Word документ с таблицей создан!", "Успех");
}

View File

@ -120,10 +120,10 @@
<metadata name="wordWithImages.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="wordWithTable.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>194, 17</value>
</metadata>
<metadata name="wordWithDiagram.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>358, 17</value>
</metadata>
<metadata name="wordWithTable.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>537, 17</value>
</metadata>
</root>

View File

@ -74,10 +74,10 @@ namespace MyCustomComponents.Helpers
return;
}
//if (config2.ColumnsRowsWidth.Count < config2.ColumnUnion[config2.ColumnUnion.Count - 1].StartIndex + config2.ColumnUnion[config2.ColumnUnion.Count - 1].Count - 1)
//{
// throw new IndexOutOfRangeException("Последнее объединение ячеек выходит за границы таблицы");
//}
if (config2.ColumnsRowsWidth.Count < config2.ColumnUnion[config2.ColumnUnion.Count - 1].StartIndex + config2.ColumnUnion[config2.ColumnUnion.Count - 1].Count - 1)
{
throw new IndexOutOfRangeException("Последнее объединение ячеек выходит за границы таблицы");
}
int k;
for (k = 0; k < config2.ColumnUnion[0].StartIndex; k++)

View File

@ -20,5 +20,12 @@
<PackageReference Include="PDFSharp.Standard.Charting" Version="1.51.15" />
<PackageReference Include="System.Drawing.Common" Version="7.0.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Aspose.Words" Version="24.9.0" />
<PackageReference Include="DocX" Version="3.0.0" />
<PackageReference Include="Spire.Doc" Version="12.8.12" />
<PackageReference Include="System.Data.OleDb" Version="8.0.0" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.6" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xceed.Document.NET;
using Xceed.Words.NET;
namespace CustomComponents.NonViewComponents.Logic
{
public abstract class WordLogicBase : IDisposable
{
protected DocX _doc;
public WordLogicBase(DocX doc)
{
_doc = doc;
}
public void Dispose()
{
_doc.Dispose();
}
protected Paragraph findParagraph(string paragraph)
=> _doc.Paragraphs.FirstOrDefault(p => p.Text.Contains(paragraph))
?? throw new Exception($"Paragraph '{paragraph}' not found.");
}
}

View File

@ -0,0 +1,114 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Xceed.Document.NET;
using Xceed.Words.NET;
namespace CustomComponents.NonViewComponents.Logic
{
public class WordTableLogic : WordLogicBase
{
private const float DEF_HEIGHT = 20;
public WordTableLogic(DocX doc) : base(doc)
{
}
public void AddTable<T>(string paragraph, IEnumerable<(string, string, string)> header,
IEnumerable<float?>? rowHeight, IEnumerable<T> values)
{
var p = findParagraph(paragraph);
var table = _doc.AddTable(header.Count(), values.Count() + 2);
table.Alignment = Alignment.center;
_addHeader(table, header);
_fillTable(table, values, header);
_formatHeader(table, header, rowHeight);
p.InsertTableAfterSelf(table);
_doc.Save();
}
private void _addHeader(Table table, IEnumerable<(string, string, string)> header)
{
for (int i = 0; i < header.Count(); i++)
{
var headerElem = header.ElementAtOrDefault(i);
table.Rows[i].Cells[0].Paragraphs[0].Append(headerElem.Item1);
table.Rows[i].Cells[1].Paragraphs[0].Append(headerElem.Item2);
}
}
private void _formatHeader(Table table, IEnumerable<(string, string,string)> header, IEnumerable<float?>? rowHeight)
{
for (int i = 0; i < header.Count(); i++)
{
var headerElem = header.ElementAtOrDefault(i);
if (string.IsNullOrWhiteSpace(headerElem.Item2))
{
table.Rows[i].MergeCells(0, 1);
}
var nextElem = header.ElementAtOrDefault(i + 1);
if (headerElem.Item1 == nextElem.Item1)
{
table.MergeCellsInColumn(0, i, i + 1);
}
table.Rows[i].Height = rowHeight?.ElementAtOrDefault(i) ?? DEF_HEIGHT;
}
}
private void _fillTable<T>(Table table, IEnumerable<T> values, IEnumerable<(string, string, string)> header)
{
for (int i = 0; i < values.Count(); i++)
{
var data = _getValueData(values.ElementAt(i), header);
_addData(table, i + 2, data);
}
}
private void _addData(Table table, int indexColumn, Dictionary<string, object> data)
{
for (int i = 0; i < data.Count; i++)
{
foreach (var cell in data)
{
if (table.Rows[i].Cells[0].Paragraphs[0].Text == cell.Key
|| table.Rows[i].Cells[1].Paragraphs[0].Text == cell.Key)
{
table.Rows[i].Cells[indexColumn].Paragraphs[0].Append(cell.Value.ToString());
}
}
}
}
private Dictionary<string, object> _getValueData<T>(T value, IEnumerable<(string, string, string)> header)
{
var result = new Dictionary<string, object>();
if (value is null)
{
throw new ArgumentNullException($"The {nameof(value)} is null.");
}
if (value.GetType().GetProperties() is null)
{
throw new ArgumentNullException($"Properties in {nameof(value)} is null");
}
foreach (var h in header)
{
var headerElem = string.IsNullOrWhiteSpace(h.Item2) ? h.Item1 : h.Item2;
var propVal = h.Item3 as string;
result[headerElem] = value.GetType().GetProperty(propVal).GetValue(value, null);
}
return result;
}
}
}

View File

@ -1,4 +1,4 @@
namespace MyCustomComponents
namespace CustomComponents.NonViewComponents
{
partial class WordWithTable
{

View File

@ -1,10 +1,4 @@
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Drawing.Charts;
using DocumentFormat.OpenXml.Drawing;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using MyCustomComponents.Helpers;
using MyCustomComponents.Models;
using CustomComponents.NonViewComponents.Logic;
using System;
using System.Collections.Generic;
using System.ComponentModel;
@ -12,56 +6,12 @@ using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xceed.Words.NET;
namespace MyCustomComponents
namespace CustomComponents.NonViewComponents
{
public partial class WordWithTable : Component
{
private Document _document = null;
private Body _body = null;
private DocumentFormat.OpenXml.Wordprocessing.Table _table = null;
private Document Document
{
get
{
if (_document == null)
{
_document = new Document();
}
return _document;
}
}
private Body Body
{
get
{
if (_body == null)
{
_body = Document.AppendChild(new Body());
}
return _body;
}
}
private DocumentFormat.OpenXml.Wordprocessing.Table Table
{
get
{
if (_table == null)
{
_table = new DocumentFormat.OpenXml.Wordprocessing.Table();
}
return _table;
}
}
public WordWithTable()
{
InitializeComponent();
@ -73,228 +23,51 @@ namespace MyCustomComponents
InitializeComponent();
}
public void CreateDoc<T>(WordWithTableDataConfig<T> config)
{
config.CheckFields();
config.ColumnsRowsDataCount = (config.Data.Count + 2, config.ColumnsRowsWidth.Count);
CreateHeader(config.Header);
CreateTableWithHeader();
CreateColumnHeader(config);
string[,] array = new string[config.ColumnsRowsWidth.Count, config.Data.Count];
for (int j = 0; j < config.Data.Count; j++)
{
int i;
for (i = 0; i < config.ColumnsRowsWidth.Count; i++)
{
(int, int, string, string) tuple = config.Headers.FirstOrDefault<(int, int, string, string)>(((int ColumnIndex, int RowIndex, string Header, string PropertyName) x) => x.ColumnIndex == i && x.RowIndex == 1);
if (tuple.Equals(default((int, int, string, string))))
{
tuple = config.Headers.FirstOrDefault<(int, int, string, string)>(((int ColumnIndex, int RowIndex, string Header, string PropertyName) x) => x.ColumnIndex == i && x.RowIndex == 0);
}
array[i, j] = config.Data[j].GetType().GetProperty(tuple.Item4)!.GetValue(config.Data[j], null)!.ToString();
/// <summary>
/// Добавляет таблицу данных после параграфа в *.docx документ.
/// Свойства объектов коллекции должны иметь атрибут <c>[DisplayName(string)]</c>.
/// Значения атрибутов должны соответствовать шапке таблицы.
/// Если в коллекции шапки ("Имя", ""), то ячейки объединяются в одну колонку.
/// Если подряд идут те же названия: ("Личная информация", "Фио"), ("Личная информация", "Город"), то ячейки объединяются в одну строку.
/// </summary>
/// <typeparam name="T">Любой класс, главное, чтобы свойства имели атрибут [DisplayName(string)]</typeparam>
/// <param name="pathToFile">Путь к документу</param>
/// <param name="paragraph">Текст внутри параграфа</param>
/// <param name="header">Информация о шапке</param>
/// <param name="rowHeight">Высота строки. Может быть null.
/// Если не указать в какой-то строке значение (поставить null, вместо float значения), то будет установлена высота по умолчанию</param>
/// <param name="values">Коллекция объектов, которые будут добавлены в таблицу</param>
public void AddTable<T>(string pathToFile, string paragraph,
IEnumerable<(string, string, string)> header,
IEnumerable<float?>? rowHeight,
IEnumerable<T> values
)
{
_check(pathToFile, paragraph, header, rowHeight, values);
using (var logic = new WordTableLogic(DocX.Load(pathToFile)))
{
logic.AddTable(paragraph, header, rowHeight, values);
}
}
private void _check<T>(string pathToFile, string paragraph,
IEnumerable<(string, string, string)> header,
IEnumerable<float?>? rowHeight,
IEnumerable<T> values)
{
if (string.IsNullOrWhiteSpace(pathToFile)
|| string.IsNullOrWhiteSpace(paragraph))
{
throw new ArgumentNullException("The path to file or paragraph is null or empty.");
}
if (rowHeight is not null)
{
if (rowHeight.Count() != header.Count())
{
throw new ArgumentException($"{nameof(rowHeight)} is not of equal length with {nameof(header)}");
}
}
LoadDataToTableWithColumnHeader(array);
SaveDoc(config.FilePath);
}
public void SaveDoc(string filepath)
{
if (filepath.IsEmpty())
{
throw new ArgumentNullException("Имя файла не задано");
}
if (_document == null || _body == null)
{
throw new ArgumentNullException("Документ не сформирован, сохранять нечего");
}
if (_table != null)
{
Body.Append(Table);
}
using WordprocessingDocument wordprocessingDocument = WordprocessingDocument.Create(filepath, WordprocessingDocumentType.Document);
MainDocumentPart mainDocumentPart = wordprocessingDocument.AddMainDocumentPart();
mainDocumentPart.Document = Document;
}
public void LoadDataToTableWithColumnHeader(string[,] data)
{
for (int i = 0; i < data.GetLength(0); i++)
{
DocumentFormat.OpenXml.Wordprocessing.TableRow tableRow = Table.Elements<DocumentFormat.OpenXml.Wordprocessing.TableRow>().ElementAt(i);
for (int j = 0; j < data.GetLength(1); j++)
{
DocumentFormat.OpenXml.Wordprocessing.TableCell tableCell = new DocumentFormat.OpenXml.Wordprocessing.TableCell();
tableCell.Append(new DocumentFormat.OpenXml.Wordprocessing.Paragraph(new DocumentFormat.OpenXml.Wordprocessing.Run(new DocumentFormat.OpenXml.Wordprocessing.Text(data[i, j]))));
tableRow.Append(tableCell);
}
}
}
private void AddColumnHeaderCellMergeByCols(string header, int rowHeight)
{
DocumentFormat.OpenXml.Wordprocessing.TableRow tableRow = new DocumentFormat.OpenXml.Wordprocessing.TableRow();
int? rowHeight2 = rowHeight;
DocumentFormat.OpenXml.Wordprocessing.TableCell tableCell = CreateCell(header, null, rowHeight2);
tableCell.Append(new HorizontalMerge
{
Val = (EnumValue<MergedCellValues>)MergedCellValues.Restart
});
tableRow.Append(tableCell);
tableCell = new DocumentFormat.OpenXml.Wordprocessing.TableCell(new DocumentFormat.OpenXml.Wordprocessing.Paragraph());
tableCell.Append(new HorizontalMerge
{
Val = (EnumValue<MergedCellValues>)MergedCellValues.Continue
});
tableRow.Append(tableCell);
Table.Append(tableRow);
}
private static DocumentFormat.OpenXml.Wordprocessing.TableCell CreateCell(string header, int? columnWidth = null, int? rowHeight = null)
{
DocumentFormat.OpenXml.Wordprocessing.TableCell tableCell = new DocumentFormat.OpenXml.Wordprocessing.TableCell();
DocumentFormat.OpenXml.Wordprocessing.TableCellProperties tableCellProperties = new DocumentFormat.OpenXml.Wordprocessing.TableCellProperties();
if (rowHeight.HasValue)
{
tableCellProperties.Append(new TableRowHeight
{
Val = (UInt32Value)Convert.ToUInt32(rowHeight)
});
}
if (columnWidth.HasValue)
{
tableCellProperties.Append(new TableCellWidth
{
Width = (StringValue)columnWidth.Value.ToString()
});
}
tableCellProperties.Append(new TableCellVerticalAlignment
{
Val = (EnumValue<TableVerticalAlignmentValues>)TableVerticalAlignmentValues.Center
});
tableCell.Append(tableCellProperties);
DocumentFormat.OpenXml.Wordprocessing.Paragraph paragraph = new DocumentFormat.OpenXml.Wordprocessing.Paragraph();
DocumentFormat.OpenXml.Wordprocessing.ParagraphProperties paragraphProperties = new DocumentFormat.OpenXml.Wordprocessing.ParagraphProperties();
paragraphProperties.Append(new Justification
{
Val = (EnumValue<JustificationValues>)JustificationValues.Center
});
paragraph.Append(paragraphProperties);
if (header.HaveText())
{
DocumentFormat.OpenXml.Wordprocessing.Run run = new DocumentFormat.OpenXml.Wordprocessing.Run();
run.AppendChild(new DocumentFormat.OpenXml.Wordprocessing.RunProperties(new Bold()));
run.AppendChild(new DocumentFormat.OpenXml.Wordprocessing.Text(header));
paragraph.Append(run);
}
tableCell.Append(paragraph);
return tableCell;
}
public void CreateColumnHeader(WordWithTableConfig config)
{
int k;
for (k = 0; k < config.ColumnUnion[0].StartIndex; k++)
{
AddColumnHeaderCellMergeByCols(config.Headers.FirstOrDefault<(int, int, string, string)>(((int ColumnIndex, int RowIndex, string Header, string PropertyName) x) => x.ColumnIndex == k).Item3, config.ColumnsRowsWidth[k].Row);
}
int j;
for (j = 0; j < config.ColumnUnion.Count; j++)
{
int l;
for (l = config.ColumnUnion[j].StartIndex; l < config.ColumnUnion[j].StartIndex + config.ColumnUnion[j].Count; l++)
{
DocumentFormat.OpenXml.Wordprocessing.TableRow tableRow = new DocumentFormat.OpenXml.Wordprocessing.TableRow();
if (l == config.ColumnUnion[j].StartIndex)
{
DocumentFormat.OpenXml.Wordprocessing.TableCell tableCell = CreateCell(config.Headers.FirstOrDefault<(int, int, string, string)>(((int ColumnIndex, int RowIndex, string Header, string PropertyName) x) => x.ColumnIndex == l && x.RowIndex == 0).Item3);
tableCell.Append(new VerticalMerge
{
Val = (EnumValue<MergedCellValues>)MergedCellValues.Restart
});
tableRow.Append(tableCell);
}
else
{
DocumentFormat.OpenXml.Wordprocessing.TableCell tableCell2 = new DocumentFormat.OpenXml.Wordprocessing.TableCell(new DocumentFormat.OpenXml.Wordprocessing.Paragraph());
tableCell2.Append(new VerticalMerge
{
Val = (EnumValue<MergedCellValues>)MergedCellValues.Continue
});
tableRow.Append(tableCell2);
}
OpenXmlElement[] array = new OpenXmlElement[1];
string item = config.Headers.FirstOrDefault<(int, int, string, string)>(((int ColumnIndex, int RowIndex, string Header, string PropertyName) x) => x.ColumnIndex == l && x.RowIndex == 1).Item3;
int? rowHeight = config.ColumnsRowsWidth[l].Row;
array[0] = CreateCell(item, null, rowHeight);
tableRow.Append(array);
Table.Append(tableRow);
}
if (j >= config.ColumnUnion.Count - 1)
{
continue;
}
for (int m = config.ColumnUnion[j].StartIndex + config.ColumnUnion[j].Count; m < config.ColumnUnion[j + 1].StartIndex; m++)
{
AddColumnHeaderCellMergeByCols(config.Headers.FirstOrDefault<(int, int, string, string)>(((int ColumnIndex, int RowIndex, string Header, string PropertyName) x) => x.ColumnIndex == j).Item3, config.ColumnsRowsWidth[j].Row);
}
}
int i;
for (i = config.ColumnUnion[config.ColumnUnion.Count - 1].StartIndex + config.ColumnUnion[config.ColumnUnion.Count - 1].Count; i < config.ColumnsRowsWidth.Count; i++)
{
AddColumnHeaderCellMergeByCols(config.Headers.FirstOrDefault<(int, int, string, string)>(((int ColumnIndex, int RowIndex, string Header, string PropertyName) x) => x.ColumnIndex == i).Item3, config.ColumnsRowsWidth[i].Row);
}
}
public void CreateTableWithHeader()
{
Table.AppendChild(new DocumentFormat.OpenXml.Wordprocessing.TableProperties(new TableBorders(new DocumentFormat.OpenXml.Wordprocessing.TopBorder
{
Val = new EnumValue<BorderValues>(BorderValues.Single),
Size = (UInt32Value)12u
}, new DocumentFormat.OpenXml.Wordprocessing.BottomBorder
{
Val = new EnumValue<BorderValues>(BorderValues.Single),
Size = (UInt32Value)12u
}, new DocumentFormat.OpenXml.Wordprocessing.LeftBorder
{
Val = new EnumValue<BorderValues>(BorderValues.Single),
Size = (UInt32Value)12u
}, new DocumentFormat.OpenXml.Wordprocessing.RightBorder
{
Val = new EnumValue<BorderValues>(BorderValues.Single),
Size = (UInt32Value)12u
}, new DocumentFormat.OpenXml.Wordprocessing.InsideHorizontalBorder
{
Val = new EnumValue<BorderValues>(BorderValues.Single),
Size = (UInt32Value)12u
}, new DocumentFormat.OpenXml.Wordprocessing.InsideVerticalBorder
{
Val = new EnumValue<BorderValues>(BorderValues.Single),
Size = (UInt32Value)12u
})));
}
public void CreateHeader(string header)
{
DocumentFormat.OpenXml.Wordprocessing.Paragraph paragraph = Body.AppendChild(new DocumentFormat.OpenXml.Wordprocessing.Paragraph());
DocumentFormat.OpenXml.Wordprocessing.Run run = paragraph.AppendChild(new DocumentFormat.OpenXml.Wordprocessing.Run());
run.AppendChild(new DocumentFormat.OpenXml.Wordprocessing.RunProperties(new Bold()));
run.AppendChild(new DocumentFormat.OpenXml.Wordprocessing.Text(header));
}
}
}