Last active
August 25, 2023 10:22
-
-
Save aspose-words-gists/93de23a2f74a7f2e4971ed203874c983 to your computer and use it in GitHub Desktop.
Aspose.Words for .NET. How to merge table cells in C#.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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)); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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; | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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"); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment