Fuse Celulele Tabelului
Uneori anumite rânduri dintr-o tabelă necesită un antet sau blocuri mari de text care ocupă întreaga lățime a tabelului. Pentru un design corect al tabelului utilizatorul poate uni mai multe celule într-una singură. Aspose.Words acceptă celule fuzionate atunci când lucrează în toate formatele de intrare, inclusiv importul conținutului HTML.
Cum să fuziuni celule de tabel
În Aspose.Words, celulele fuzionate sunt reprezentate de următoarele proprietăți ale clasei CellFormat:
- HorizontalMerge care descrie dacă celula este o parte dintr-o fuziune orizontală de celule
- VerticalMerge care descrie dacă celula face parte dintr-o fuziune verticală de celule
Valorile acestor proprietăți determină comportamentul de fuziune a celulelor
“- prima celulă dintr-o secvență de celule fuzionate va avea CellMerge.First”
- Orice celule fuzionate ulterior vor avea CellMerge.Previous
- O celulă care nu este fuzionată va avea CellMerge.None
Verificaţi dacă celula este fuzionată
Pentru a verifica dacă o celulă este parte dintr-o secvență de celule fuzionate, verificăm pur și simplu proprietățile HorizontalMerge și VerticalMerge.
Exemplul de cod următor arată cum să se imprime tipul de fuziune a celulelor orizontale și verticale:
// 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)); | |
} | |
} |
Fuziunea celulelor de tabel atunci când se utilizează document builder-ul
Pentru a combina celule într-o tabelă creată cu DocumentBuilder, trebuie să setați tipul de combinare corespunzător pentru fiecare celulă unde se așteaptă combinarea – mai întâi CellMerge.First și apoi CellMerge.Previous.
De asemenea, trebuie să ţii minte să elimini setarea de fuziune pentru celulele în care nu este necesară fuziunea – aceasta poate fi făcută prin setarea primei celule nefuziate la CellMerge.None. Dacă nu se face asta, toate celulele din tabel vor fi fuzionate.
Exemplul de cod următor arată cum să creezi o tabelă cu două rânduri în care celulele din primul rând sunt fuzionate orizontal:
// 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"); |
Exemplul următor de cod arată cum să creezi o tabelă cu două coloane, unde celulele din prima coloană sunt fuzionate vertical:
// 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"); |
Fuse Celulele Tabelului în Alte Cazuri
În alte situații în care DocumentBuilder nu este folosit, cum ar fi într-o masă existentă, fuzionarea celulelor în acest fel poate să nu fie la fel de ușoară. În schimb, putem înveli operațiile de bază implicate în aplicarea proprietăților de fuziune la celule într-o metodă care face sarcina mult mai ușoară. Acest metod este asemanator cu metoda de automatizare Merge, care se apeleaza pentru a combina o gama de celule intr-o tabelă.
Codul de mai jos va uni celulele din intervalul specificat, începând cu celula dată și terminând la celula de sfârșit. În acest caz, intervalul poate să cuprindă mai multe rânduri sau coloane:
// 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; | |
} | |
} | |
} | |
} |
Exemplul de cod următor arată cum să uniți un interval de celule între două celule specificate:
// 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"); |
În funcție de versiunea .NET Framework pe care o utilizați, poate doriți să rafinați această metodă prin transformarea acesteia într-o metodă extensie. În acest caz, poţi apela direct această metodă pe o celulă pentru a combina un interval de celule, cum ar fi cell1.Merge(cell2)
.
Celule verticale și orizontale fuzionate în HTML tabel
Așa cum am spus în articolele anterioare, un tabel în Microsoft Word este un set de rânduri independente. Fiecare rând are un set de celule care sunt independente de celulele altor rânduri. Aşadar, în Microsoft Word tabel nu există un astfel de obiect ca o “coloană”, iar “1-a coloană” este ceva asemănător cu “setul de 1-e celule din fiecare rând din tabel”. Acest lucru permite utilizatorilor să aibă o masă în care, de exemplu, rândul 1 constă din două celule - 2 cm și 1 cm, iar rândul 2 constă din două celule diferite - 1 cm și 2 cm largi. Și Aspose.Words suportă această concepție de tabele.
O masă în HTML are o structură esențial diferită: fiecare rând are același număr de celule și (este important pentru sarcină) fiecare celulă are lățimea coloanei corespunzătoare, aceeași pentru toate celulele din unu rând. Deci dacă HorizontalMerge și VerticalMerge returnează o valoare incorectă, folosiți exemplul de cod următor:
// 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; | |
} |
Converteste la celule fuzionate orizontal
Uneori nu este posibil să se detecteze care celule sunt fuzionate deoarece unele versiuni mai noi ale Microsoft Word nu utilizează steagurile de fuziune atunci când celulele sunt fuzionate orizontal. Dar pentru situaţii în care celulele sunt fuzionate într-o singură celulă orizontal prin lățimea lor folosind steaguri de fuziune, Aspose.Words oferă metoda ConvertToHorizontallyMergedCells
pentru a converti celulele. Această metodă transformă pur și simplu tabelul și adaugă noi celule după cum este necesar.
Exemplul următor de cod arată metoda de mai sus în acțiune":
// 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(); |