Сливане на таблици клетки
Понякога някои редове в таблица изискват заглавие или големи блокове от текст, които заемат пълната ширина на таблицата. За правилното проектиране на масата, потребителят може да слее няколко клетки на масата в една. Aspose.Words поддържа слетите клетки при работа с всички входни формати, включително внос на HTML съдържание.
Как да се сливат клетки маса
В Aspose.Words, Слетите клетки са представени от следните свойства на CellFormat клас:
- HorizontalMerge което описва дали клетката е част от хоризонтално сливане на клетки
- VerticalMerge което описва дали клетката е част от вертикално сливане на клетки
Стойностите на тези свойства определят сливането на поведението на клетките:
- Първата клетка в поредица от слети клетки ще има CellMerge.First
- Всички впоследствие слети клетки ще имат CellMerge.Previous
- Клетка, която не се слива ще има CellMerge.None
Проверете дали клетката е разбъркана
За да проверим дали клетката е част от поредица от слети клетки, просто проверяваме HorizontalMerge както и VerticalMerge имоти.
Следният пример за код показва как да отпечатате типа хоризонтално и вертикално сливане на клетки:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET.git. | |
Document doc = new Document(MyDir + "Table with merged cells.docx"); | |
Table table = (Table) doc.GetChild(NodeType.Table, 0, true); | |
foreach (Row row in table.Rows) | |
{ | |
foreach (Cell cell in row.Cells) | |
{ | |
Console.WriteLine(PrintCellMergeType(cell)); | |
} | |
} |
Сливане на таблици клетки при използване на документ строител
Сливане на клетките в таблица, създадена с DocumentBuilder, трябва да зададете подходящия тип сливане за всяка клетка, където сливането се очаква. CellMerge.First и тогава CellMerge.Previous.
Също така, не трябва да забравяте да изчистите настройката за сливане за тези клетки, където не се изисква сливане. CellMerge.None. Ако това не се направи, всички клетки в таблицата ще бъдат обединени.
Следният пример за код показва как да се създаде таблица с два реда, където клетките в първия ред се сливат хоризонтално:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET.git. | |
Document doc = new Document(); | |
DocumentBuilder builder = new DocumentBuilder(doc); | |
builder.InsertCell(); | |
builder.CellFormat.HorizontalMerge = CellMerge.First; | |
builder.Write("Text in merged cells."); | |
builder.InsertCell(); | |
// This cell is merged to the previous and should be empty. | |
builder.CellFormat.HorizontalMerge = CellMerge.Previous; | |
builder.EndRow(); | |
builder.InsertCell(); | |
builder.CellFormat.HorizontalMerge = CellMerge.None; | |
builder.Write("Text in one cell."); | |
builder.InsertCell(); | |
builder.Write("Text in another cell."); | |
builder.EndRow(); | |
builder.EndTable(); | |
doc.Save(ArtifactsDir + "WorkingWithTables.HorizontalMerge.docx"); |
Следният пример за код показва как да се създаде таблица с две колони, в която клетките в първата колона се сливат вертикално:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET.git. | |
Document doc = new Document(); | |
DocumentBuilder builder = new DocumentBuilder(doc); | |
builder.InsertCell(); | |
builder.CellFormat.VerticalMerge = CellMerge.First; | |
builder.Write("Text in merged cells."); | |
builder.InsertCell(); | |
builder.CellFormat.VerticalMerge = CellMerge.None; | |
builder.Write("Text in one cell"); | |
builder.EndRow(); | |
builder.InsertCell(); | |
// This cell is vertically merged to the cell above and should be empty. | |
builder.CellFormat.VerticalMerge = CellMerge.Previous; | |
builder.InsertCell(); | |
builder.CellFormat.VerticalMerge = CellMerge.None; | |
builder.Write("Text in another cell"); | |
builder.EndRow(); | |
builder.EndTable(); | |
doc.Save(ArtifactsDir + "WorkingWithTables.VerticalMerge.docx"); |
Сливане на таблици клетки в други случаи
В други ситуации, когато DocumentBuilder не се използва, като например в съществуваща таблица, сливането на клетките по предишния начин може да не е толкова лесно. Вместо това можем да увием основните операции, свързани с прилагането на сливащи се свойства към клетките в метод, който улеснява задачата. Този метод е подобен на метода за сливане на автоматизация, който се нарича сливане на набор от клетки в таблица.
Кодът по-долу ще слее клетките на таблицата в определения диапазон, като се започне от дадена клетка и завършва в крайната клетка. В този случай обхватът може да обхваща няколко реда или колони:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET.git. | |
internal void MergeCells(Cell startCell, Cell endCell) | |
{ | |
Table parentTable = startCell.ParentRow.ParentTable; | |
// Find the row and cell indices for the start and end cell. | |
Point startCellPos = new Point(startCell.ParentRow.IndexOf(startCell), | |
parentTable.IndexOf(startCell.ParentRow)); | |
Point endCellPos = new Point(endCell.ParentRow.IndexOf(endCell), parentTable.IndexOf(endCell.ParentRow)); | |
// Create a range of cells to be merged based on these indices. | |
// Inverse each index if the end cell is before the start cell. | |
Rectangle mergeRange = new Rectangle(Math.Min(startCellPos.X, endCellPos.X), | |
Math.Min(startCellPos.Y, endCellPos.Y), | |
Math.Abs(endCellPos.X - startCellPos.X) + 1, Math.Abs(endCellPos.Y - startCellPos.Y) + 1); | |
foreach (Row row in parentTable.Rows) | |
{ | |
foreach (Cell cell in row.Cells) | |
{ | |
Point currentPos = new Point(row.IndexOf(cell), parentTable.IndexOf(row)); | |
// Check if the current cell is inside our merge range, then merge it. | |
if (mergeRange.Contains(currentPos)) | |
{ | |
cell.CellFormat.HorizontalMerge = currentPos.X == mergeRange.X ? CellMerge.First : CellMerge.Previous; | |
cell.CellFormat.VerticalMerge = currentPos.Y == mergeRange.Y ? CellMerge.First : CellMerge.Previous; | |
} | |
} | |
} | |
} |
Следният пример за код показва как да се слее набор от клетки между две определени клетки:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET.git. | |
Document doc = new Document(MyDir + "Table with merged cells.docx"); | |
Table table = doc.FirstSection.Body.Tables[0]; | |
// We want to merge the range of cells found inbetween these two cells. | |
Cell cellStartRange = table.Rows[0].Cells[0]; | |
Cell cellEndRange = table.Rows[1].Cells[1]; | |
// Merge all the cells between the two specified cells into one. | |
MergeCells(cellStartRange, cellEndRange); | |
doc.Save(ArtifactsDir + "WorkingWithTables.MergeCellRange.docx"); |
В зависимост от версията на .NET Framework Вие използвате, може да искате да усъвършенствате този метод чрез превръщането му в метод на разширение. В този случай, можете да се обадите на този метод директно на клетка, за да се слее набор от клетки, като cell1.Merge(cell2)
.
Вертикални и хоризонтални свързващи клетки в HTML таблица
Както казахме в предишните статии, таблица в Microsoft Word е набор от независими редове. Всеки ред има набор от клетки, които са независими от клетките на други редове. По този начин в Microsoft Word таблица не съществува такъв обект като готварски, а първата колона е нещо като набор от 1-ви клетки на всеки ред в таблицата. Това позволява на потребителите да имат таблица, в която, например, 1-ви ред се състои от две клетки 2см и 1см, а 2-ри ред се състои от два различни клетки, които са широки 1см и 2см. И Aspose.Words поддържа тази концепция за масите.
Таблица в HTML има по същество различна структура: всеки ред има еднакъв брой клетки и (това е важно за задачата) всяка клетка има широчината на съответната колона, еднаква за всички клетки в една колона. Така че, ако HorizontalMerge както и VerticalMerge връщане на неправилна стойност, използвайте следния пример с код:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET.git. | |
Document doc = new Document(MyDir + "Table with merged cells.docx"); | |
SpanVisitor visitor = new SpanVisitor(doc); | |
doc.Accept(visitor); |
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET.git. | |
/// <summary> | |
/// Helper class that contains collection of rowinfo for each row. | |
/// </summary> | |
public class TableInfo | |
{ | |
public List<RowInfo> Rows { get; } = new List<RowInfo>(); | |
} | |
/// <summary> | |
/// Helper class that contains collection of cellinfo for each cell. | |
/// </summary> | |
public class RowInfo | |
{ | |
public List<CellInfo> Cells { get; } = new List<CellInfo>(); | |
} | |
/// <summary> | |
/// Helper class that contains info about cell. currently here is only colspan and rowspan. | |
/// </summary> | |
public class CellInfo | |
{ | |
public CellInfo(int colSpan, int rowSpan) | |
{ | |
ColSpan = colSpan; | |
RowSpan = rowSpan; | |
} | |
public int ColSpan { get; } | |
public int RowSpan { get; } | |
} | |
public class SpanVisitor : DocumentVisitor | |
{ | |
/// <summary> | |
/// Creates new SpanVisitor instance. | |
/// </summary> | |
/// <param name="doc"> | |
/// Is document which we should parse. | |
/// </param> | |
public SpanVisitor(Document doc) | |
{ | |
mWordTables = doc.GetChildNodes(NodeType.Table, true); | |
// We will parse HTML to determine the rowspan and colspan of each cell. | |
MemoryStream htmlStream = new MemoryStream(); | |
Aspose.Words.Saving.HtmlSaveOptions options = new Aspose.Words.Saving.HtmlSaveOptions | |
{ | |
ImagesFolder = Path.GetTempPath() | |
}; | |
doc.Save(htmlStream, options); | |
// Load HTML into the XML document. | |
XmlDocument xmlDoc = new XmlDocument(); | |
htmlStream.Position = 0; | |
xmlDoc.Load(htmlStream); | |
// Get collection of tables in the HTML document. | |
XmlNodeList tables = xmlDoc.DocumentElement.GetElementsByTagName("table"); | |
foreach (XmlNode table in tables) | |
{ | |
TableInfo tableInf = new TableInfo(); | |
// Get collection of rows in the table. | |
XmlNodeList rows = table.SelectNodes("tr"); | |
foreach (XmlNode row in rows) | |
{ | |
RowInfo rowInf = new RowInfo(); | |
// Get collection of cells. | |
XmlNodeList cells = row.SelectNodes("td"); | |
foreach (XmlNode cell in cells) | |
{ | |
// Determine row span and colspan of the current cell. | |
XmlAttribute colSpanAttr = cell.Attributes["colspan"]; | |
XmlAttribute rowSpanAttr = cell.Attributes["rowspan"]; | |
int colSpan = colSpanAttr == null ? 0 : int.Parse(colSpanAttr.Value); | |
int rowSpan = rowSpanAttr == null ? 0 : int.Parse(rowSpanAttr.Value); | |
CellInfo cellInf = new CellInfo(colSpan, rowSpan); | |
rowInf.Cells.Add(cellInf); | |
} | |
tableInf.Rows.Add(rowInf); | |
} | |
mTables.Add(tableInf); | |
} | |
} | |
public override VisitorAction VisitCellStart(Cell cell) | |
{ | |
int tabIdx = mWordTables.IndexOf(cell.ParentRow.ParentTable); | |
int rowIdx = cell.ParentRow.ParentTable.IndexOf(cell.ParentRow); | |
int cellIdx = cell.ParentRow.IndexOf(cell); | |
int colSpan = 0; | |
int rowSpan = 0; | |
if (tabIdx < mTables.Count && | |
rowIdx < mTables[tabIdx].Rows.Count && | |
cellIdx < mTables[tabIdx].Rows[rowIdx].Cells.Count) | |
{ | |
colSpan = mTables[tabIdx].Rows[rowIdx].Cells[cellIdx].ColSpan; | |
rowSpan = mTables[tabIdx].Rows[rowIdx].Cells[cellIdx].RowSpan; | |
} | |
Console.WriteLine("{0}.{1}.{2} colspan={3}\t rowspan={4}", tabIdx, rowIdx, cellIdx, colSpan, rowSpan); | |
return VisitorAction.Continue; | |
} | |
private readonly List<TableInfo> mTables = new List<TableInfo>(); | |
private readonly NodeCollection mWordTables; | |
} |
Конвертиране хоризонтално Разделени клетки
Понякога не е възможно да се открият кои клетки се сливат, защото някои по-нови версии на Microsoft Word не използват повече сливащи се флагове, когато клетките се сливат хоризонтално. Но за ситуации, в които клетките се сливат в клетка хоризонтално по широчина, използвайки сливащи се флагове, Aspose.Words осигурява ConvertToHorizontallyMergedCells
метод за преобразуване на клетките. Този метод просто трансформира таблицата и добавя нови клетки, когато е необходимо.
Следният пример с код показва гореспоменатия метод в действие:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET.git. | |
Document doc = new Document(MyDir + "Table with merged cells.docx"); | |
Table table = doc.FirstSection.Body.Tables[0]; | |
// Now merged cells have appropriate merge flags. | |
table.ConvertToHorizontallyMergedCells(); |