Tablo Hücrelerini Birleştir

Bazen bir tablodaki belirli satırlar, tablonun tüm genişliğini kaplayan bir başlık veya büyük metin blokları gerektirir. Tablonun doğru tasarımı için kullanıcı birkaç tablo hücresini tek bir hücrede birleştirebilir. Aspose.Words, HTML içeriğinin içe aktarılması da dahil olmak üzere tüm giriş formatlarıyla çalışırken birleştirilmiş hücreleri destekler.

Tablo Hücreleri Nasıl Birleştirilir

Aspose.Words’te birleştirilmiş hücreler, CellFormat sınıfının aşağıdaki özellikleriyle temsil edilir:

  • Hücrenin yatay hücre birleşiminin parçası olup olmadığını açıklayan HorizontalMerge
  • Hücrenin dikey hücre birleşiminin parçası olup olmadığını açıklayan VerticalMerge

Bu özelliklerin değerleri hücrelerin birleştirme davranışını belirler:

Hücrenin Birleştirilip Birleştirilmediğini Kontrol Edin

Bir hücrenin birleştirilmiş hücre dizisinin parçası olup olmadığını kontrol etmek için HorizontalMerge ve VerticalMerge özelliklerini kontrol etmemiz yeterlidir.

Aşağıdaki kod örneği, yatay ve dikey hücre birleştirme türünün nasıl yazdırılacağını gösterir:

// 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’ı Kullanırken Tablo Hücrelerini Birleştir

DocumentBuilder ile oluşturulan bir tablodaki hücreleri birleştirmek için, birleştirmenin beklendiği her hücre için uygun birleştirme türünü (önce CellMerge.First, ardından CellMerge.Previous) ayarlamanız gerekir.

Ayrıca, birleştirmenin gerekli olmadığı hücreler için birleştirme ayarını temizlemeyi de unutmamalısınız; bu, birleştirilmeyen ilk hücreyi CellMerge.None olarak ayarlayarak yapılabilir. Bu yapılmazsa tablodaki tüm hücreler birleştirilecektir.

Aşağıdaki kod örneği, ilk satırdaki hücrelerin yatay olarak birleştirildiği iki satırlı bir tablonun nasıl oluşturulacağını gösterir:

// 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");

Aşağıdaki kod örneği, ilk sütundaki hücrelerin dikey olarak birleştirildiği iki sütunlu bir tablonun nasıl oluşturulacağını gösterir:

// 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");

Diğer Durumlarda Tablo Hücrelerini Birleştir

Mevcut bir tabloda olduğu gibi DocumentBuilder‘in kullanılmadığı diğer durumlarda, hücreleri önceki yöntemle birleştirmek o kadar kolay olmayabilir. Bunun yerine, birleştirme özelliklerinin hücrelere uygulanmasıyla ilgili temel işlemleri, görevi çok daha kolay hale getiren bir yöntemle tamamlayabiliriz. Bu yöntem, bir tablodaki hücre aralığını birleştirmek için çağrılan Birleştirme otomasyonu yöntemine benzer.

Aşağıdaki kod, belirtilen aralıktaki tablo hücrelerini, verilen hücreden başlayıp son hücreye kadar birleştirecektir. Bu durumda aralık birden çok satıra veya sütuna yayılabilir:

// 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;
}
}
}
}
view raw merge-cells.cs hosted with ❤ by GitHub

Aşağıdaki kod örneği, belirli iki hücre arasında bir hücre aralığının nasıl birleştirileceğini gösterir:

// 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");

Kullandığınız .NET Framework sürümüne bağlı olarak bu yöntemi bir uzantı yöntemine dönüştürerek geliştirmek isteyebilirsiniz. Bu durumda, cell1.Merge(cell2) gibi bir hücre aralığını birleştirmek için bu yöntemi doğrudan bir hücre üzerinde çağırabilirsiniz.

HTML Tablosunda Dikey ve Yatay Birleştirilmiş Hücreler

Önceki yazılarımızda da söylediğimiz gibi Microsoft Word’teki bir tablo, bağımsız satırlardan oluşan bir kümedir. Her satırda diğer satırların hücrelerinden bağımsız bir dizi hücre bulunur. Dolayısıyla Microsoft Word tablosunda “sütun” diye bir nesne yoktur ve “1. sütun”, “tablodaki her satırın 1. hücrelerinin kümesi” gibi bir şeydir. Bu, kullanıcıların örneğin 1. satırın 2cm ve 1cm genişliğinde iki hücreden oluştuğu ve 2. satırın 1cm ve 2cm genişliğinde iki farklı hücreden oluştuğu bir masaya sahip olmasına olanak tanır. Ve Aspose.Words bu tablo konseptini desteklemektedir.

HTML’deki bir tablo temelde farklı bir yapıya sahiptir: her satır aynı sayıda hücreye sahiptir ve (görev için önemlidir) her hücre, bir sütundaki tüm hücreler için aynı olan, karşılık gelen sütunun genişliğine sahiptir. HorizontalMerge ve VerticalMerge yanlış bir değer döndürürse aşağıdaki kod örneğini kullanın:

// 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;
}

Yatay Olarak Birleştirilmiş Hücrelere Dönüştür

Bazen Microsoft Word’in bazı yeni sürümleri, hücreler yatay olarak birleştirildiğinde artık birleştirme işaretlerini kullanmadığından hangi hücrelerin birleştirildiğini tespit etmek mümkün olmayabilir. Ancak hücrelerin, birleştirme bayrakları kullanılarak genişliklerine göre yatay olarak bir hücrede birleştirildiği durumlarda, Aspose.Words, hücreleri dönüştürmek için ConvertToHorizontallyMergedCells yöntemini sağlar. Bu yöntem basitçe tabloyu dönüştürür ve gerektiğinde yeni hücreler ekler.

Aşağıdaki kod örneği, yukarıdaki yöntemin çalışmasını gösterir:

// 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();