표 셀 병합
때로는 표의 특정 행에 표의 전체 너비를 차지하는 제목이나 큰 텍스트 블록이 필요한 경우가 있습니다. 테이블의 적절한 디자인을 위해 사용자는 여러 테이블 셀을 하나로 병합할 수 있습니다. 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 사용 시 테이블 셀 병합
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"); |
다음 코드 예제에서는 첫 번째 열의 셀이 수직으로 병합되는 2열 테이블을 만드는 방법을 보여줍니다
// 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 테이블에는 “열"과 같은 개체가 없으며 “첫 번째 열"은 “테이블의 각 행의 첫 번째 셀 집합"과 같습니다. 이를 통해 사용자는 예를 들어 첫 번째 행이 2cm와 1cm의 두 셀로 구성되고 두 번째 행은 너비가 1cm와 2cm인 두 개의 서로 다른 셀로 구성된 테이블을 가질 수 있습니다. 그리고 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(); |