Fusionner Les Cellules Du Tableau
Parfois, certaines lignes d’un tableau nécessitent un en-tête ou de gros blocs de texte qui occupent toute la largeur du tableau. Pour une conception correcte du tableau, l’utilisateur peut fusionner plusieurs cellules du tableau en une seule. Aspose.Words prend en charge les cellules fusionnées lorsque vous travaillez avec tous les formats d’entrée, y compris l’importation de contenu HTML.
Comment Fusionner des Cellules de Tableau
Dans Aspose.Words, les cellules fusionnées sont représentées par les propriétés suivantes de la classe CellFormat:
- HorizontalMerge qui décrit si la cellule fait partie d’une fusion horizontale de cellules
- VerticalMerge qui décrit si la cellule fait partie d’une fusion verticale de cellules
Les valeurs de ces propriétés déterminent le comportement de fusion des cellules:
- La première cellule d’une séquence de cellules fusionnées aura CellMerge.First
- Toutes les cellules fusionnées ultérieurement auront CellMerge.Previous
- Une cellule qui n’est pas fusionnée aura CellMerge.None
Vérifier si une cellule est fusionnée
Pour vérifier si une cellule fait partie d’une séquence de cellules fusionnées, nous vérifions simplement les propriétés HorizontalMerge et VerticalMerge.
L’exemple de code suivant montre comment imprimer le type de fusion de cellule horizontale et verticale:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-Java.git. | |
Document doc = new Document(getMyDir() + "Table with merged cells.docx"); | |
Table table = (Table) doc.getChild(NodeType.TABLE, 0, true); | |
for (Row row : (Iterable<Row>) table.getRows()) | |
{ | |
for (Cell cell : (Iterable<Cell>) row.getCells()) | |
{ | |
System.out.println(printCellMergeType(cell)); | |
} | |
} |
Fusionner Les Cellules Du Tableau Lors De L’Utilisation De DocumentBuilder
Pour fusionner des cellules dans un tableau créé avec le DocumentBuilder, vous devez définir le type de fusion approprié pour chaque cellule où la fusion est attendue-d’abord CellMerge.First puis CellMerge.Previous.
De plus, vous devez vous rappeler d’effacer le paramètre de fusion pour les cellules où aucune fusion n’est requise – cela peut être fait en définissant la première cellule non fusionnée sur CellMerge.None. Si cela n’est pas fait, toutes les cellules du tableau seront fusionnées.
L’exemple de code suivant montre comment créer un tableau avec deux lignes où les cellules de la première ligne sont fusionnées horizontalement:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-Java.git. | |
Document doc = new Document(); | |
DocumentBuilder builder = new DocumentBuilder(doc); | |
builder.insertCell(); | |
builder.getCellFormat().setHorizontalMerge(CellMerge.FIRST); | |
builder.write("Text in merged cells."); | |
builder.insertCell(); | |
// This cell is merged to the previous and should be empty. | |
builder.getCellFormat().setHorizontalMerge(CellMerge.PREVIOUS); | |
builder.endRow(); | |
builder.insertCell(); | |
builder.getCellFormat().setHorizontalMerge(CellMerge.NONE); | |
builder.write("Text in one cell."); | |
builder.insertCell(); | |
builder.write("Text in another cell."); | |
builder.endRow(); | |
builder.endTable(); | |
doc.save(getArtifactsDir() + "WorkingWithTables.HorizontalMerge.docx"); |
L’exemple de code suivant montre comment créer un tableau à deux colonnes dans lequel les cellules de la première colonne sont fusionnées verticalement:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-Java.git. | |
Document doc = new Document(); | |
DocumentBuilder builder = new DocumentBuilder(doc); | |
builder.insertCell(); | |
builder.getCellFormat().setVerticalMerge(CellMerge.FIRST); | |
builder.write("Text in merged cells."); | |
builder.insertCell(); | |
builder.getCellFormat().setVerticalMerge(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.getCellFormat().setVerticalMerge(CellMerge.PREVIOUS); | |
builder.insertCell(); | |
builder.getCellFormat().setVerticalMerge(CellMerge.NONE); | |
builder.write("Text in another cell"); | |
builder.endRow(); | |
builder.endTable(); | |
doc.save(getArtifactsDir() + "WorkingWithTables.VerticalMerge.docx"); |
Fusionner des Cellules de Tableau dans D’Autres Cas
Dans d’autres situations où le DocumentBuilder n’est pas utilisé, comme dans un tableau existant, la fusion des cellules de la manière précédente peut ne pas être aussi simple. Au lieu de cela, nous pouvons envelopper les opérations de base impliquées dans l’application des propriétés de fusion aux cellules dans une méthode qui rend la tâche beaucoup plus facile. Cette méthode est similaire à la méthode d’automatisation de fusion, qui est appelée pour fusionner une plage de cellules dans un tableau.
Le code ci-dessous fusionnera les cellules du tableau dans la plage spécifiée, en commençant par la cellule donnée et en se terminant par la cellule de fin. Dans ce cas, la plage peut s’étendre sur plusieurs lignes ou colonnes:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-Java.git. | |
void mergeCells(Cell startCell, Cell endCell) | |
{ | |
Table parentTable = startCell.getParentRow().getParentTable(); | |
// Find the row and cell indices for the start and end cell. | |
Point startCellPos = new Point(startCell.getParentRow().indexOf(startCell), | |
parentTable.indexOf(startCell.getParentRow())); | |
Point endCellPos = new Point(endCell.getParentRow().indexOf(endCell), parentTable.indexOf(endCell.getParentRow())); | |
// 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.y), | |
Math.min(startCellPos.y, endCellPos.y), | |
Math.abs(endCellPos.x - startCellPos.x) + 1, Math.abs(endCellPos.y - startCellPos.y) + 1); | |
for (Row row : parentTable.getRows()) | |
{ | |
for (Cell cell : row.getCells()) | |
{ | |
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.getCellFormat().setHorizontalMerge(currentPos.x == mergeRange.getX() ? CellMerge.FIRST : CellMerge.PREVIOUS); | |
cell.getCellFormat().setVerticalMerge(currentPos.y == mergeRange.getY() ? CellMerge.FIRST : CellMerge.PREVIOUS); | |
} | |
} | |
} | |
} |
L’exemple de code suivant montre comment fusionner une plage de cellules entre deux cellules spécifiées:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-Java.git. | |
Document doc = new Document(getMyDir() + "Table with merged cells.docx"); | |
Table table = doc.getFirstSection().getBody().getTables().get(0); | |
// We want to merge the range of cells found inbetween these two cells. | |
Cell cellStartRange = table.getRows().get(0).getCells().get(0); | |
Cell cellEndRange = table.getRows().get(1).getCells().get(1); | |
// Merge all the cells between the two specified cells into one. | |
mergeCells(cellStartRange, cellEndRange); | |
doc.save(getArtifactsDir() + "WorkingWithTables.MergeCellRange.docx"); |
Cellules fusionnées verticales et horizontales dans le tableau HTML
Comme nous l’avons dit dans les articles précédents, une table dans Microsoft Word est un ensemble de lignes indépendantes. Chaque ligne comporte un ensemble de cellules indépendantes des cellules des autres lignes. Ainsi, dans le tableau Microsoft Word, il n’y a pas d’objet tel qu’une “colonne”, et “1ère colonne” est quelque chose comme “l’ensemble des 1ères cellules de chaque ligne du tableau”. Cela permet aux utilisateurs d’avoir un tableau dans lequel, par exemple, la 1ère rangée se compose de deux cellules – 2cm et 1cm, et la 2ème rangée se compose de deux cellules différentes – 1cm et 2cm de large. Et Aspose.Words supporte ce concept de tables.
Un tableau dans HTML a une structure essentiellement différente: chaque ligne a le même nombre de cellules et (c’est important pour la tâche) chaque cellule a la largeur de la colonne correspondante, la même pour toutes les cellules d’une colonne. Donc, si HorizontalMerge et VerticalMerge renvoient une valeur incorrecte, utilisez l’exemple de code suivant:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-Java.git. | |
Document doc = new Document(getMyDir() + "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-Java.git. | |
/// <summary> | |
/// Helper class that contains collection of rowinfo for each row. | |
/// </summary> | |
public static class TableInfo | |
{ | |
public ArrayList<RowInfo> getRows() { return mRows; } | |
private ArrayList<RowInfo> mRows = new ArrayList<>(); | |
} | |
/// <summary> | |
/// Helper class that contains collection of cellinfo for each cell. | |
/// </summary> | |
public static class RowInfo | |
{ | |
public ArrayList<CellInfo> getCells() { return mCells; }; | |
private ArrayList<CellInfo> mCells = new ArrayList<>(); | |
} | |
/// <summary> | |
/// Helper class that contains info about cell. currently here is only colspan and rowspan. | |
/// </summary> | |
public static class CellInfo | |
{ | |
public CellInfo(int colSpan, int rowSpan) | |
{ | |
mColSpan = colSpan; | |
mRowSpan = rowSpan; | |
} | |
public int getColSpan() { return mColSpan; }; | |
private int mColSpan; | |
public int getRowSpan() { return mRowSpan; }; | |
private int mRowSpan; | |
} | |
public static class SpanVisitor extends DocumentVisitor | |
{ | |
/// <summary> | |
/// Creates new SpanVisitor instance. | |
/// </summary> | |
/// <param name="doc"> | |
/// Is document which we should parse. | |
/// </param> | |
public SpanVisitor(Document doc) throws Exception { | |
mWordTables = doc.getChildNodes(NodeType.TABLE, true); | |
// We will parse HTML to determine the rowspan and colspan of each cell. | |
ByteArrayOutputStream htmlStream = new ByteArrayOutputStream(); | |
HtmlSaveOptions options = new HtmlSaveOptions(); | |
{ | |
options.setImagesFolder(System.getProperty("java.io.tmpdir")); | |
} | |
doc.save(htmlStream, options); | |
// Load HTML into the XML document. | |
org.jsoup.nodes.Document document = Jsoup.parse(htmlStream.toString()); | |
// Get collection of tables in the HTML document. | |
Elements tables = document.getElementsByTag("table"); | |
for (Element table : tables) { | |
TableInfo tableInf = new TableInfo(); | |
// Get collection of rows in the table. | |
Elements rows = table.getElementsByTag("tr"); | |
for (Element row : rows) { | |
RowInfo rowInf = new RowInfo(); | |
// Get collection of cells. | |
Elements cells = row.getElementsByTag("td"); | |
for (Element cell : cells) { | |
// Determine row span and colspan of the current cell. | |
String colSpanAttr = cell.attributes().get("colspan"); | |
String rowSpanAttr = cell.attributes().get("rowspan"); | |
int colSpan = StringUtils.isNotBlank(colSpanAttr) ? Integer.parseInt(colSpanAttr) : 0; | |
int rowSpan = StringUtils.isNotBlank(rowSpanAttr) ? Integer.parseInt(rowSpanAttr) : 0; | |
CellInfo cellInf = new CellInfo(colSpan, rowSpan); | |
rowInf.getCells().add(cellInf); | |
} | |
tableInf.getRows().add(rowInf); | |
} | |
mTables.add(tableInf); | |
} | |
} | |
public int visitCellStart(Cell cell) | |
{ | |
int tabIdx = mWordTables.indexOf(cell.getParentRow().getParentTable()); | |
int rowIdx = cell.getParentRow().getParentTable().indexOf(cell.getParentRow()); | |
int cellIdx = cell.getParentRow().indexOf(cell); | |
int colSpan = 0; | |
int rowSpan = 0; | |
if (tabIdx < mTables.size() && | |
rowIdx < mTables.get(tabIdx).getRows().size() && | |
cellIdx < mTables.get(tabIdx).getRows().get(rowIdx).getCells().size()) | |
{ | |
colSpan = mTables.get(tabIdx).getRows().get(rowIdx).getCells().get(cellIdx).getColSpan(); | |
rowSpan = mTables.get(tabIdx).getRows().get(rowIdx).getCells().get(cellIdx).getRowSpan(); | |
} | |
System.out.println(MessageFormat.format("{0}.{1}.{2} colspan={3}\t rowspan={4}", tabIdx, rowIdx, cellIdx, colSpan, rowSpan)); | |
return VisitorAction.CONTINUE; | |
} | |
private ArrayList<TableInfo> mTables = new ArrayList<>(); | |
private NodeCollection mWordTables; | |
} |
Convertir en cellules fusionnées horizontalement
Parfois, il n’est pas possible de détecter quelles cellules sont fusionnées car certaines versions plus récentes de Microsoft Word n’utilisent plus les indicateurs de fusion lorsque les cellules sont fusionnées horizontalement. Mais pour les situations où les cellules sont fusionnées horizontalement en une cellule par leur largeur à l’aide des indicateurs de fusion, Aspose.Words fournit la méthode ConvertToHorizontallyMergedCells
pour convertir les cellules. Cette méthode transforme simplement le tableau et ajoute de nouvelles cellules au besoin.
L’exemple de code suivant montre la méthode ci-dessus en fonctionnement:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-Java.git. | |
Document doc = new Document(getMyDir() + "Table with merged cells.docx"); | |
Table table = doc.getFirstSection().getBody().getTables().get(0); | |
// Now merged cells have appropriate merge flags. | |
table.convertToHorizontallyMergedCells(); |